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

# Contrats

> Rôle des contrats Laravel, différences avec les façades, injection par type-hint et création de contrats personnalisés.

## Qu'est-ce qu'un contrat

Les « Contracts » de Laravel sont un ensemble d'interfaces qui définissent les services centraux fournis par le framework. Par exemple, le contrat `Illuminate\Contracts\Queue\Queue` définit les méthodes nécessaires pour mettre en file d'attente des jobs, et `Illuminate\Contracts\Mail\Mailer` définit les méthodes nécessaires pour envoyer des e-mails.

Chaque contrat possède une implémentation fournie par le framework. Par exemple, Laravel fournit des implémentations de file pour divers drivers, et un mailer basé sur [Symfony Mailer](https://symfony.com/doc/current/mailer.html).

Tous les contrats Laravel se trouvent dans un [dépôt GitHub dédié](https://github.com/illuminate/contracts). Ce dépôt sert de référence rapide aux contrats disponibles et constitue un package isolé utilisable pour construire des packages qui s'intègrent aux services Laravel.

<Info>
  Un contrat n'est qu'une interface. Il fonctionne comme n'importe quelle interface PHP. Laravel fournit une implémentation et l'injecte via le conteneur de services.
</Info>

## Différences entre contrat et façade

Les [façades](/fr/facades) et les fonctions helper permettent d'utiliser facilement les services Laravel sans devoir résoudre un contrat via un type-hint. Dans la plupart des cas, à chaque façade correspond un contrat.

Différences majeures :

| Aspect                    | Façade                                  | Contrat                                                      |
| ------------------------- | --------------------------------------- | ------------------------------------------------------------ |
| Déclaration de dépendance | Inutile (appelable partout)             | Déclarée explicitement dans le constructeur                  |
| Tests                     | Mock via `shouldReceive()`              | Remplacement via une bibliothèque de mock standard           |
| Usage principal           | Utilisation pratique dans l'application | Développement de packages, gestion explicite des dépendances |
| Lisibilité                | Importation en une ligne                | Dépendances visibles dans le constructeur                    |

<Tip>
  Les façades n'ont pas besoin d'être déclarées dans le constructeur, alors que les contrats se déclarent explicitement comme dépendances. Certains développeurs préfèrent cette déclaration explicite et utilisent les contrats. D'autres apprécient la commodité des façades. **En général, les façades conviennent à la plupart des applications sans problème.**
</Tip>

## Quand utiliser un contrat

Le choix entre contrats et façades relève de la préférence personnelle ou d'équipe. Les deux permettent d'écrire des applications Laravel robustes et testables. Ils ne s'excluent pas : vous pouvez utiliser les façades dans certaines parties et les contrats dans d'autres.

Les contrats sont particulièrement utiles pour :

* **Construire un package qui s'intègre à plusieurs frameworks PHP** — en utilisant le package `illuminate/contracts`, vous définissez l'intégration avec les services Laravel sans exiger une implémentation concrète dans `composer.json`.
* **Rendre explicites les dépendances** — regarder le constructeur suffit à voir de quoi la classe dépend.
* **Remplacer une implémentation** — le remplacement via le conteneur de services devient très simple.

## Utiliser un contrat

Comment récupérer l'implémentation d'un contrat ? C'est très simple.

Contrôleurs, listeners, middlewares, jobs de queue, closures de routes… de nombreux types de classes Laravel sont résolus via le conteneur. Pour obtenir l'implémentation d'un contrat, il suffit de le « type-hinter » dans le constructeur de la classe.

```mermaid theme={null}
flowchart LR
    A["Service provider<br>bind(Interface, Impl)"] --> B["Conteneur de services<br>Enregistrement du binding"]
    C["Constructeur<br>Type-hint : Interface"] --> B
    B --> D["Injection automatique<br>Résolution de l'implémentation"]
    D --> E["Instance concrète<br>Remplaçable librement"]
```

Par exemple, ce listener :

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

namespace App\Listeners;

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

class CacheOrderInformation
{
    /**
     * Crée un nouveau listener.
     */
    public function __construct(
        protected Factory $redis,
    ) {}

    /**
     * Traite l'événement.
     */
    public function handle(OrderWasPlaced $event): void
    {
        // ...
    }
}
```

Lorsque le listener est résolu, le conteneur lit les type-hints du constructeur et injecte la valeur appropriée.

## Créer un contrat personnalisé

Créer vos propres contrats clarifie les dépendances entre composants.

<Steps>
  <Step title="Définir l'interface">
    Créez l'interface dans `app/Contracts`.

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

    namespace App\Contracts;

    interface PaymentGateway
    {
        /**
         * Débite le montant donné.
         */
        public function charge(int $amount, string $token): bool;

        /**
         * Rembourse le paiement.
         */
        public function refund(string $transactionId): bool;
    }
    ```
  </Step>

  <Step title="Créer une implémentation">
    Créez la classe qui implémente le contrat.

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

    namespace App\Services;

    use App\Contracts\PaymentGateway;

    class StripePaymentGateway implements PaymentGateway
    {
        public function charge(int $amount, string $token): bool
        {
            // Traitement du paiement via l'API Stripe...
            return true;
        }

        public function refund(string $transactionId): bool
        {
            // Traitement du remboursement via l'API Stripe...
            return true;
        }
    }
    ```
  </Step>

  <Step title="Enregistrer le binding dans un service provider">
    Reliez le contrat à son implémentation dans un [service provider](/fr/service-providers).

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

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

  <Step title="Recevoir l'injection via type-hint">
    Utilisez le type-hint dans le constructeur d'un contrôleur ou d'une autre classe.

    ```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>

Grâce à ce pattern, changer de fournisseur (`Stripe` vers un autre) revient à modifier un seul binding — sans toucher au contrôleur.

## Principaux contrats

Contrats fréquents et leurs façades correspondantes (extrait).

| Contrat                                         | Façade correspondante |
| ----------------------------------------------- | --------------------- |
| `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`                |

La liste complète est disponible dans le dépôt [illuminate/contracts](https://github.com/illuminate/contracts).

## Prochaines étapes

<Card title="Façades" icon="layer-group" href="/fr/facades">
  Revenez sur le fonctionnement et les tests des façades.
</Card>


## Related topics

- [Créer un agent personnalisé pour Boost](/fr/advanced/boost-custom-agent.md)
- [Les nouveautés de Laravel 13](/fr/blog/laravel-13-new-features.md)
- [Guide de mise à niveau de Laravel 12 vers 13](/fr/blog/upgrade-12-to-13.md)
- [Créer un fournisseur personnalisé pour l'AI SDK](/fr/advanced/ai-sdk-custom-provider.md)
- [Façades](/fr/facades.md)
