Cada integración que entrega tu equipo sigue el mismo estándar predecible. Los desarrolladores nuevos entienden cualquier API en minutos — no en días. OAuth2 automático, peticiones en paralelo y DTOs tipados incluidos. Un solo bundle de Symfony — destilado de tres años de integraciones en producción.
Cada API añadida sin un estándar le cuesta a tu equipo días de configuración y se acumula con cada nueva integración. URLs hardcodeadas, lógica OAuth duplicada, arrays filtrándose al dominio — la siguiente siempre es más difícil que la anterior.
Tiempo desde cero hasta una integración funcionando y testeada — incluyendo OAuth, llamadas en paralelo y respuestas tipadas.
Genera la action, el mapper y la respuesta para cualquier endpoint. Todo el equipo genera la misma estructura, siempre.
Se instala junto al código existente. Los nuevos endpoints siguen el estándar; las integraciones legacy migran a tu ritmo.
sendManyOrFail() despacha todas las peticiones en paralelo. El tiempo total ≈ la petición más lenta — independientemente de cuántas envíes. En producción, una búsqueda de disponibilidad en Booking.com requiere 4 consultas en paralelo para una ciudad pequeña y 17 para París — por cliente. Esto lo gestiona.
$requests = []; foreach ($stationIds as $key => $params) { $requests[$key] = EngineRequest::create( actionName: GetStationByIdAction::getName(), context: DefaultActionContext::create($params), ); } // All dispatched concurrently — total time ≈ slowest request $results = $this->engine->sendManyOrFail($requests);
Se instala junto al código existente. Sin reescritura masiva — usa el patrón en el próximo endpoint nuevo y migra el código legacy a tu ritmo.
Añade la lógica y 3 líneas al MyApi.yaml — listo.
Auth dinámica, batch requests y contextos personalizados están en la documentación.
Leer la documentación →$ php bin/console make:integration MyApi GetUser MyApi/ ├─ MyApi.yaml ← añade aquí el entry del endpoint └─ GetUser/ ├─ Request/GetUserAction.php ← método HTTP, path, auth └─ Response/ ├─ GetUserResponse.php ← DTO tipado └─ GetUserMapper.php ← array crudo → DTO # Nuevo endpoint, misma integración: $ php bin/console make:integration MyApi CreateOrder # → Añade CreateOrder/ junto a GetUser/. Los ficheros existentes nunca se sobreescriben.¿Qué va dentro de los ficheros generados? Ver la documentación →
Un entry en YAML. Un mapper. Una respuesta tipada. El refresco del token OAuth2 se gestiona automáticamente — sin lógica de tokens en tu código de aplicación.
GetToken: action: App\...\GetTokenAction method: POST path: /v1/oauth/token CreatePaymentIntent: action: App\...\CreatePaymentIntentAction method: POST path: /v1/payment_intents authorization: type: dynamic action: GetToken token_field: access_token ttl: 3600
Cada frontera de infraestructura es una interfaz. Cambia el cliente HTTP, personaliza la resolución de rutas o añade soporte batch — sin tocar el engine.
Reemplaza el cliente HTTP. Etiqueta tu implementación y el engine la descubre automáticamente vía Symfony DI.
Lógica de rutas más compleja que los {placeholders}. Devuelve null para caer al resolver por defecto.
Marca tu cliente como batch-capable para despacho concurrente. El cliente REST incluido ya lo implementa.
Test doubles incluidos. Testea mappers y actions en aislamiento — sin mocks, sin HTTP real.
¿Listo para añadir el patrón a tu próximo proyecto?
Los mismos endpoints, dos implementaciones. Cada sección muestra las clases reales del proyecto.
base_url o añades autenticación, hay un único punto de cambio.StationDto::fromApiData() es el único punto de contacto. Si la API cambia un campo, hay exactamente un sitio que tocar.RailwayApiService y sus convenciones privadas (_hasPhoto). Con StationService como única frontera, los controllers solo importan objetos del dominio y el coste de cambiar de proveedor queda reducido a un solo fichero.sendMany() devuelve un BatchResultCollection donde inspeccionas cada resultado; sendManyOrFail() lanza en el primer fallo después de que todo el batch haya ejecutado. El cliente REST por defecto ya implementa BatchClientInterface mediante las lazy responses de Symfony HttpClient — cero configuración adicional.Llevo tres años usando este patrón en producción — integrando Booking.com, Iberia, Lleego, Hostalia y más. Solo la disponibilidad de Booking.com requiere 4 consultas en paralelo para una ciudad pequeña, 17 para París, por cliente. Una versión anterior de este engine lo gestionaba sin inmutarse. Este bundle es lo que esos tres años me enseñaron: hecho explícito, testeado y abierto.
Escríbenos directamente, abre una GitHub Discussion, o instálalo y pruébalo.