> ## 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（契約）

> 說明 Laravel Contracts 的角色、與 Facade 的差異、透過型別提示注入的方式，以及建立自訂 Contract 的方法。

## 什麼是 Contract

Laravel 的「Contracts」是一組定義框架所提供核心服務的介面。例如，`Illuminate\Contracts\Queue\Queue` Contract 定義了 Job 佇列所需的方法；`Illuminate\Contracts\Mail\Mailer` Contract 則定義了寄送郵件所需的方法。

每個 Contract 都有框架提供的對應實作。例如，Laravel 提供各種驅動的佇列實作，以及使用 [Symfony Mailer](https://symfony.com/doc/current/mailer.html) 的 mailer 實作。

所有 Laravel Contracts 都放在[專用的 GitHub Repository](https://github.com/illuminate/contracts) 中。這是一個獨立且已抽離的套件，提供所有可用 Contract 的快速參考，非常適合在打造與 Laravel 服務串接的套件時使用。

<Info>
  Contract 只是介面，運作方式與 PHP 的介面完全相同。Laravel 為這些介面提供實作，並透過服務容器注入。
</Info>

## Contract 與 Facade 的差異

[Facade](/zh-TW/facades) 與輔助函式提供一種便利的方式，可以不必透過服務容器的型別提示解析 Contract 即能使用 Laravel 的服務。多數情況下，每個 Facade 都對應到一個 Contract。

Facade 與 Contract 主要差異如下：

| 觀點    | Facade                   | Contract      |
| ----- | ------------------------ | ------------- |
| 依賴的宣告 | 不需要（任何地方皆可呼叫）            | 於建構子明確宣告      |
| 測試    | 以 `shouldReceive()` mock | 以標準 mock 工具替換 |
| 主要用途  | 應用程式中方便使用                | 套件開發、明確的相依管理  |
| 程式可讀性 | 只需一行 import              | 建構子即可清楚看到相依   |

<Tip>
  Facade 不需要在建構子中要求，但 Contract 可作為明確依賴宣告於建構子。部分開發者偏好這種明確的依賴宣告而使用 Contract；也有部分開發者偏好 Facade 的便利。**通常，大多數應用程式在開發時使用 Facade 都能運作良好。**
</Tip>

## 何時使用 Contract

選擇 Contract 或 Facade 通常是個人偏好或團隊風格。兩者都能協助你建立健全且易於測試的 Laravel 應用程式，而且兩者並非互斥。你可以在部分區塊使用 Facade，其他區塊仰賴 Contract。

以下情境下 Contract 特別有用：

* **要與多個 PHP 框架協作的套件**：使用 `illuminate/contracts` 套件來定義與 Laravel 服務的介接，就不必在 `composer.json` 中要求 Laravel 具體實作。
* **想讓依賴顯式**：只看建構子就能一眼看出這個類別依賴什麼。
* **想更換實作**：透過服務容器可以輕鬆換成別的實作。

## Contract 的使用方式

如何取得 Contract 的實作？其實非常簡單。

Laravel 中許多種類的類別，如控制器、事件監聽器、中介軟體、佇列 Job、路由閉包等，都是透過服務容器解析而來。因此，要取得 Contract 的實作，只需在被解析類別的建構子上「型別提示」該介面。

```mermaid theme={null}
flowchart LR
    A["服務提供者<br>bind(Interface, Impl)"] --> B["服務容器<br>註冊繫結"]
    C["建構子<br>型別提示：Interface"] --> B
    B --> D["自動注入<br>解析 Interface 的實作"]
    D --> E["具體類別的實例<br>可自由替換"]
```

以下是一個事件監聽器範例：

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

namespace App\Listeners;

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

class CacheOrderInformation
{
    /**
     * 建立事件監聽器
     */
    public function __construct(
        protected Factory $redis,
    ) {}

    /**
     * 處理事件
     */
    public function handle(OrderWasPlaced $event): void
    {
        // ...
    }
}
```

當事件監聽器被解析時，服務容器會讀取類別建構子的型別提示，並注入對應的值。

## 建立自訂 Contract

透過建立自己的 Contract，可以讓應用程式各組件間的相依關係更清晰。

<Steps>
  <Step title="定義介面">
    在 `app/Contracts` 目錄建立介面。

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

    namespace App\Contracts;

    interface PaymentGateway
    {
        /**
         * 收取指定金額
         */
        public function charge(int $amount, string $token): bool;

        /**
         * 退款
         */
        public function refund(string $transactionId): bool;
    }
    ```
  </Step>

  <Step title="建立實作類別">
    建立實作 Contract 的類別。

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

    namespace App\Services;

    use App\Contracts\PaymentGateway;

    class StripePaymentGateway implements PaymentGateway
    {
        public function charge(int $amount, string $token): bool
        {
            // 使用 Stripe API 進行收款...
            return true;
        }

        public function refund(string $transactionId): bool
        {
            // 使用 Stripe API 進行退款...
            return true;
        }
    }
    ```
  </Step>

  <Step title="在服務提供者中繫結">
    在[服務提供者](/zh-TW/service-providers)中將 Contract 與實作繫結。

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

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

  <Step title="透過型別提示接收注入">
    在控制器或其他類別的建構子加上型別提示。

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

這種模式讓你日後想把金流服務由 `Stripe` 換成別的供應商時，只需修改一處繫結，控制器程式碼完全不必變動。

## 主要 Contract 一覽

以下為部分常用 Contract 與其對應 Facade 的對照表。

| Contract                                        | 對應 Facade             |
| ----------------------------------------------- | --------------------- |
| `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`                |

所有 Contract 的完整清單請見 [illuminate/contracts](https://github.com/illuminate/contracts) repository。

## 下一步

<Card title="Facade" icon="layer-group" href="/zh-TW/facades">
  了解 Facade 的機制與測試方式。
</Card>


## Related topics

- [建立 AI SDK 的自定義 Provider](/zh-TW/advanced/ai-sdk-custom-provider.md)
- [Facade](/zh-TW/facades.md)
- [建立 Boost 的自定義 Agent](/zh-TW/advanced/boost-custom-agent.md)
- [Laravel 13 新功能彙總](/zh-TW/blog/laravel-13-new-features.md)
- [Collection Deep Dive](/zh-TW/advanced/collection-deep-dive.md)
