¿Qué es un Contract?
Los “Contracts” de Laravel son un conjunto de interfaces que definen los servicios principales que ofrece el framework. Por ejemplo, el ContractIlluminate\Contracts\Queue\Queue define los métodos necesarios para encolar jobs, y Illuminate\Contracts\Mail\Mailer define los necesarios para enviar correos.
Cada Contract tiene su implementación correspondiente proporcionada por el framework. Por ejemplo, Laravel ofrece implementaciones de cola para distintos drivers y un mailer basado en Symfony Mailer.
Todos los Contracts de Laravel están en un repositorio de GitHub dedicado. Es una referencia rápida a todos los Contracts disponibles y un paquete aislado que puedes usar para construir paquetes que se integran con los servicios de Laravel.
Un Contract es simplemente una interfaz. Funciona exactamente igual que cualquier otra interfaz de PHP. Laravel proporciona una implementación para cada una y la inyecta a través del contenedor de servicios.
Diferencia entre Contract y Facade
Las facades y las funciones helper ofrecen una forma sencilla de usar los servicios de Laravel sin necesidad de resolver un Contract mediante type-hinting desde el contenedor. En la mayoría de los casos, cada facade tiene su Contract equivalente. Las principales diferencias son:| Aspecto | Facade | Contract |
|---|---|---|
| Declaración de dependencia | No es necesaria (se llama desde cualquier lugar) | Se declara explícitamente en el constructor |
| Pruebas | Se mockea con shouldReceive() | Se sustituye con librerías de mock estándar |
| Uso principal | Uso cómodo dentro de la aplicación | Desarrollo de paquetes, gestión explícita de dependencias |
| Legibilidad | Basta una línea de import | Las dependencias se ven de un vistazo en el constructor |
Cuándo usar Contracts
Elegir entre Contract y Facade depende del gusto personal o del gusto del equipo. Ambos permiten crear aplicaciones Laravel robustas y fáciles de testear. No son excluyentes: puedes usar Facades en una parte de la aplicación y Contracts en otra. Los Contracts resultan especialmente útiles en estos casos:- Construir paquetes que se integran con varios frameworks PHP: usando el paquete
illuminate/contractspuedes definir la integración con los servicios de Laravel sin exigir implementaciones concretas de Laravel en tucomposer.json. - Hacer explícitas las dependencias: basta con leer el constructor para saber de qué depende la clase.
- Intercambiar implementaciones: es fácil sustituir por otra implementación a través del contenedor de servicios.
Cómo usar un Contract
¿Cómo se obtiene la implementación de un Contract? Es muy sencillo. Muchas clases de Laravel (controladores, listeners de eventos, middlewares, jobs de cola, closures de ruta, etc.) se resuelven a través del contenedor de servicios. Para obtener la implementación de un Contract basta con hacer “type-hint” de la interfaz en el constructor de la clase que se resuelve. Por ejemplo, mira este listener:Creación de un Contract propio
Crear un Contract propio te permite dejar claras las dependencias entre los componentes de tu aplicación.Registrar el binding en un service provider
Registra la relación Contract / implementación en un service provider.
Stripe a otro, basta con modificar el binding en un solo sitio, y el código del controlador no cambia.
Lista de Contracts principales
Tabla de correspondencia (parcial) entre Contracts habituales y sus facades.| Contract | Facade correspondiente |
|---|---|
Illuminate\Contracts\Auth\Access\Gate | Gate |
Illuminate\Contracts\Auth\Factory | Auth |
Illuminate\Contracts\Bus\Dispatcher | Bus |
Illuminate\Contracts\Cache\Factory | Cache |
Illuminate\Contracts\Cache\Repository | Cache::driver() |
Illuminate\Contracts\Config\Repository | Config |
Illuminate\Contracts\Console\Kernel | Artisan |
Illuminate\Contracts\Container\Container | App |
Illuminate\Contracts\Encryption\Encrypter | Crypt |
Illuminate\Contracts\Events\Dispatcher | Event |
Illuminate\Contracts\Filesystem\Factory | Storage |
Illuminate\Contracts\Filesystem\Filesystem | Storage::disk() |
Illuminate\Contracts\Hashing\Hasher | Hash |
Illuminate\Contracts\Mail\Mailer | Mail |
Illuminate\Contracts\Notifications\Dispatcher | Notification |
Illuminate\Contracts\Queue\Factory | Queue |
Illuminate\Contracts\Queue\Queue | Queue::connection() |
Illuminate\Contracts\Queue\ShouldQueue | — |
Illuminate\Contracts\Redis\Factory | Redis |
Illuminate\Contracts\Routing\ResponseFactory | Response |
Illuminate\Contracts\Routing\UrlGenerator | URL |
Illuminate\Contracts\Session\Session | Session::driver() |
Illuminate\Contracts\Translation\Translator | Lang |
Illuminate\Contracts\Validation\Factory | Validator |
Illuminate\Contracts\View\Factory | View |
Próximos pasos
Facades
Descubre el funcionamiento y las técnicas de prueba de las facades.