> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Contracts (contratos)

> Explicamos el papel de los Contracts en Laravel, sus diferencias con las facades, cómo inyectarlos mediante type-hinting y cómo crear Contracts propios.

## ¿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 Contract `Illuminate\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](https://symfony.com/doc/current/mailer.html).

Todos los Contracts de Laravel están en un [repositorio de GitHub dedicado](https://github.com/illuminate/contracts). 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.

<Info>
  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.
</Info>

## Diferencia entre Contract y Facade

Las [facades](/es/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   |

<Tip>
  Las facades no requieren declararse en el constructor de la clase, mientras que los Contracts se definen como dependencias explícitas ahí. Algunos desarrolladores prefieren esa dependencia explícita y usan Contracts; otros prefieren la comodidad de las facades. **En general, la mayoría de las aplicaciones pueden usar facades sin problemas durante su desarrollo.**
</Tip>

## 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/contracts` puedes definir la integración con los servicios de Laravel sin exigir implementaciones concretas de Laravel en tu `composer.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.

```mermaid theme={null}
flowchart LR
    A["Service provider<br>bind(Interface, Impl)"] --> B["Contenedor de servicios<br>Registro de binding"]
    C["Constructor<br>type-hint: Interface"] --> B
    B --> D["Inyección automática<br>Resolución de la implementación"]
    D --> E["Instancia de la clase concreta<br>Intercambiable"]
```

Por ejemplo, mira este listener:

```php theme={null}
<?php

namespace App\Listeners;

use App\Events\OrderWasPlaced;
use App\Models\User;
use Illuminate\Contracts\Redis\Factory;

class CacheOrderInformation
{
    /**
     * Crea el listener del evento
     */
    public function __construct(
        protected Factory $redis,
    ) {}

    /**
     * Maneja el evento
     */
    public function handle(OrderWasPlaced $event): void
    {
        // ...
    }
}
```

Cuando se resuelve el listener, el contenedor lee los type-hints del constructor de la clase e inyecta los valores adecuados.

## Creación de un Contract propio

Crear un Contract propio te permite dejar claras las dependencias entre los componentes de tu aplicación.

<Steps>
  <Step title="Definir la interfaz">
    Crea la interfaz en el directorio `app/Contracts`.

    ```php theme={null}
    <?php

    namespace App\Contracts;

    interface PaymentGateway
    {
        /**
         * Cobra el importe indicado
         */
        public function charge(int $amount, string $token): bool;

        /**
         * Reembolsa un pago
         */
        public function refund(string $transactionId): bool;
    }
    ```
  </Step>

  <Step title="Crear la clase de implementación">
    Crea una clase que implemente el Contract.

    ```php theme={null}
    <?php

    namespace App\Services;

    use App\Contracts\PaymentGateway;

    class StripePaymentGateway implements PaymentGateway
    {
        public function charge(int $amount, string $token): bool
        {
            // Procesamiento del pago vía la API de Stripe...
            return true;
        }

        public function refund(string $transactionId): bool
        {
            // Reembolso vía la API de Stripe...
            return true;
        }
    }
    ```
  </Step>

  <Step title="Registrar el binding en un service provider">
    Registra la relación Contract / implementación en un [service provider](/es/service-providers).

    ```php theme={null}
    use App\Contracts\PaymentGateway;
    use App\Services\StripePaymentGateway;

    $this->app->singleton(PaymentGateway::class, StripePaymentGateway::class);
    ```
  </Step>

  <Step title="Recibir la inyección por type-hint">
    Añade el type-hint en el constructor del controlador o clase que lo necesite.

    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use App\Contracts\PaymentGateway;
    use Illuminate\Http\Request;

    class OrderController extends Controller
    {
        public function __construct(
            protected PaymentGateway $payment,
        ) {}

        public function store(Request $request)
        {
            $this->payment->charge(
                $request->amount,
                $request->payment_token
            );

            // ...
        }
    }
    ```
  </Step>
</Steps>

Con este patrón, si cambias tu proveedor de pagos de `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`                 |

Puedes consultar la lista completa de Contracts en el repositorio [illuminate/contracts](https://github.com/illuminate/contracts).

## Próximos pasos

<Card title="Facades" icon="layer-group" href="/es/facades">
  Descubre el funcionamiento y las técnicas de prueba de las facades.
</Card>


## Related topics

- [Crear un proveedor personalizado del AI SDK](/es/advanced/ai-sdk-custom-provider.md)
- [Support Contracts (Arrayable / Jsonable / Htmlable / Responsable)](/es/advanced/support-contracts.md)
- [Facades](/es/facades.md)
- [Laravel Boost](/es/boost.md)
- [Crear un agente personalizado de Boost](/es/advanced/boost-custom-agent.md)
