跳到主要內容

套件開發

📝 此頁面為 Laravel 官方文檔的繁體中文翻譯。查看原始英文版本

套件開發

簡介

套件是向 Laravel 添加功能的主要方式。套件可以是任何東西,從像 Carbon 這樣處理日期的好方法,到像 Spatie 的 Laravel Media Library 這樣允許您將檔案與 Eloquent 模型關聯的套件。

有不同類型的套件。有些套件是獨立的,意味著它們可以與任何 PHP 框架一起使用。Carbon 和 Pest 是獨立套件的範例。這些套件都可以透過在 composer.json 檔案中要求它們來與 Laravel 一起使用。

另一方面,其他套件專門設計用於與 Laravel 一起使用。這些套件可能有專門旨在增強 Laravel 應用程式的路由、控制器、視圖和配置。本指南主要涵蓋那些特定於 Laravel 的套件的開發。

關於外觀的說明

編寫 Laravel 應用程式時,通常無論您使用合約還是外觀都沒有關係,因為兩者都提供了基本相同的可測試性水平。但是,編寫套件時,您的套件通常無法存取所有 Laravel 的測試輔助工具。如果您希望能夠像套件安裝在典型 Laravel 應用程式中一樣編寫套件測試,您可以使用 Orchestral Testbench 套件。

套件自動發現

Laravel 應用程式的 bootstrap/providers.php 檔案包含應由 Laravel 載入的服務提供者列表。但是,與其要求使用者手動將您的服務提供者添加到列表中,您可以在套件的 composer.json 檔案的 extra 部分定義提供者,以便 Laravel 自動載入它。除了服務提供者之外,您還可以列出您希望註冊的任何外觀

"extra": {
    "laravel": {
        "providers": [
            "Barryvdh\\Debugbar\\ServiceProvider"
        ],
        "aliases": {
            "Debugbar": "Barryvdh\\Debugbar\\Facade"
        }
    }
},

一旦您的套件配置了自動發現,Laravel 將在安裝時自動註冊其服務提供者和外觀,為套件使用者建立便利的安裝體驗。

選擇退出套件自動發現

如果您是套件的使用者並希望禁用某個套件的套件自動發現,您可以在應用程式的 composer.json 檔案的 extra 部分列出套件名稱:

"extra": {
    "laravel": {
        "dont-discover": [
            "barryvdh/laravel-debugbar"
        ]
    }
},

您可以使用 * 字元在應用程式的 dont-discover 指令中禁用所有套件的套件自動發現:

"extra": {
    "laravel": {
        "dont-discover": [
            "*"
        ]
    }
},

服務提供者

服務提供者是您的套件與 Laravel 之間的連接點。服務提供者負責將事物綁定到 Laravel 的服務容器中,並告知 Laravel 在哪裡載入套件資源,如視圖、配置和語言檔案。

服務提供者擴展 Illuminate\Support\ServiceProvider 類別,並包含兩個方法:registerboot。基礎 ServiceProvider 類別位於 illuminate/support Composer 套件中,您應該將其添加到自己套件的依賴項中。要了解更多關於服務提供者的結構和目的,請查閱其文件

資源

配置

通常,您需要將套件的配置檔案發佈到應用程式的 config 目錄中。這將允許套件使用者輕鬆覆蓋您的預設配置選項。要允許發佈您的配置檔案,請從服務提供者的 boot 方法中呼叫 publishes 方法:

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    $this->publishes([
        __DIR__.'/../config/courier.php' => config_path('courier.php'),
    ]);
}

現在,當套件使用者執行 Laravel 的 vendor:publish 命令時,您的檔案將被複製到指定的發佈位置。一旦您的配置被發佈,其值可以像任何其他配置檔案一樣被存取:

$value = config('courier.option');

[!WARNING] 您不應在配置檔案中定義閉包。當使用者執行 config:cache Artisan 命令時,它們無法正確序列化。

預設套件配置

您還可以將自己的套件配置檔案與應用程式已發佈的副本合併。這將允許使用者僅定義他們實際想要在配置檔案的已發佈副本中覆蓋的選項。要合併配置檔案值,請在服務提供者的 register 方法中使用 mergeConfigFrom 方法。

mergeConfigFrom 方法接受套件配置檔案的路徑作為其第一個參數,應用程式配置檔案副本的名稱作為其第二個參數:

/**
 * 註冊任何套件服務。
 */
public function register(): void
{
    $this->mergeConfigFrom(
        __DIR__.'/../config/courier.php', 'courier'
    );
}

[!WARNING] 此方法僅合併配置陣列的第一層。如果使用者部分定義了多維配置陣列,則不會合併缺少的選項。

路由

如果您的套件包含路由,您可以使用 loadRoutesFrom 方法載入它們。此方法將自動判斷應用程式的路由是否已快取,並且如果路由已被快取,則不會載入您的路由檔案:

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    $this->loadRoutesFrom(__DIR__.'/../routes/web.php');
}

遷移

如果您的套件包含資料庫遷移,您可以使用 publishesMigrations 方法告知 Laravel 給定目錄或檔案包含遷移。當 Laravel 發佈遷移時,它將自動更新其檔案名中的時間戳以反映當前日期和時間:

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    $this->publishesMigrations([
        __DIR__.'/../database/migrations' => database_path('migrations'),
    ]);
}

語言檔案

如果您的套件包含語言檔案,您可以使用 loadTranslationsFrom 方法告知 Laravel 如何載入它們。例如,如果您的套件名為 courier,您應該將以下內容添加到服務提供者的 boot 方法中:

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');
}

套件翻譯行使用 package::file.line 語法慣例來引用。因此,您可以像這樣從 messages 檔案中載入 courier 套件的 welcome 行:

echo trans('courier::messages.welcome');

您可以使用 loadJsonTranslationsFrom 方法為套件註冊 JSON 翻譯檔案。此方法接受包含套件 JSON 翻譯檔案的目錄路徑:

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    $this->loadJsonTranslationsFrom(__DIR__.'/../lang');
}

發佈語言檔案

如果您希望將套件的語言檔案發佈到應用程式的 lang/vendor 目錄,可以使用服務提供者的 publishes 方法。publishes 方法接受一個套件路徑陣列及其期望的發佈位置。例如,要發佈 courier 套件的語言檔案,您可以執行以下操作:

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');

    $this->publishes([
        __DIR__.'/../lang' => $this->app->langPath('vendor/courier'),
    ]);
}

現在,當套件使用者執行 Laravel 的 vendor:publish Artisan 命令時,套件的語言檔案將被發佈到指定的發佈位置。

視圖

要向 Laravel 註冊套件的視圖,您需要告知 Laravel 視圖位於何處。您可以使用服務提供者的 loadViewsFrom 方法來實現。此方法接受兩個參數:視圖範本的路徑和套件的名稱。例如,如果套件的名稱是 courier,您應該將以下內容添加到服務提供者的 boot 方法中:

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');
}

套件視圖使用 package::view 語法慣例來引用。因此,一旦您的視圖路徑在服務提供者中註冊,您就可以像這樣從 courier 套件中載入 dashboard 視圖:

Route::get('/dashboard', function () {
    return view('courier::dashboard');
});

覆蓋套件視圖

當您使用 loadViewsFrom 方法時,Laravel 實際上為您的視圖註冊了兩個位置:應用程式的 resources/views/vendor 目錄和您指定的目錄。因此,以 courier 套件為例,Laravel 將首先檢查是否已將視圖的自訂版本放入開發者的 resources/views/vendor/courier 目錄中。然後,如果視圖未被自訂,Laravel 將搜尋您在呼叫 loadViewsFrom 時指定的套件視圖目錄。這使得套件使用者可以輕鬆地自訂/覆蓋套件的視圖。

發佈視圖

如果您希望使視圖可供發佈到應用程式的 resources/views/vendor 目錄,可以使用服務提供者的 publishes 方法。publishes 方法接受一個套件視圖路徑陣列及其期望的發佈位置:

/**
 * 啟動套件服務。
 */
public function boot(): void
{
    $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');

    $this->publishes([
        __DIR__.'/../resources/views' => resource_path('views/vendor/courier'),
    ]);
}

現在,當套件使用者執行 Laravel 的 vendor:publish Artisan 命令時,套件的視圖將被複製到指定的發佈位置。

視圖元件

如果您正在建立一個使用 Blade 元件或將元件放置在非傳統目錄中的套件,則需要手動註冊元件類別及其 HTML 標籤別名,以便 Laravel 知道在哪裡找到該元件。您通常應該在套件服務提供者的 boot 方法中註冊元件:

use Illuminate\Support\Facades\Blade;
use VendorPackage\View\Components\AlertComponent;

/**
 * 啟動套件的服務。
 */
public function boot(): void
{
    Blade::component('package-alert', AlertComponent::class);
}

一旦註冊了元件,就可以使用其標籤別名來渲染它:

<x-package-alert/>

自動載入套件元件

或者,您可以使用 componentNamespace 方法按慣例自動載入元件類別。例如,Nightshade 套件可能有一個 Calendar 和一個 ColorPicker 元件,它們位於 Nightshade\Views\Components 命名空間中:

use Illuminate\Support\Facades\Blade;

/**
 * 啟動套件的服務。
 */
public function boot(): void
{
    Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}

這將允許使用 package-name:: 語法透過供應商命名空間使用套件元件:

<x-nightshade::calendar />
<x-nightshade::color-picker />

Blade 將透過將元件名稱帕斯卡化來自動偵測連結到此元件的類別。也支援使用「點」表示法的子目錄。

匿名元件

如果您的套件包含匿名元件,它們必須放置在套件的「views」目錄的 components 目錄中(如 loadViewsFrom 方法所指定)。然後,您可以透過在元件名稱前加上套件的視圖命名空間來渲染它們:

<x-courier::alert />

「About」Artisan 命令

Laravel 的內建 about Artisan 命令提供應用程式環境和配置的概要。套件可以透過 AboutCommand 類別將額外資訊推送到此命令的輸出中。通常,可以從套件服務提供者的 boot 方法添加此資訊:

use Illuminate\Foundation\Console\AboutCommand;

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    AboutCommand::add('My Package', fn () => ['Version' => '1.0.0']);
}

命令

要向 Laravel 註冊套件的 Artisan 命令,您可以使用 commands 方法。此方法接受一個命令類別名稱陣列。一旦註冊了命令,您就可以使用 Artisan CLI 執行它們:

use Courier\Console\Commands\InstallCommand;
use Courier\Console\Commands\NetworkCommand;

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->commands([
            InstallCommand::class,
            NetworkCommand::class,
        ]);
    }
}

優化命令

Laravel 的優化命令會快取應用程式的配置、事件、路由和視圖。使用 optimizes 方法,您可以註冊套件自己的 Artisan 命令,這些命令應在執行 optimizeoptimize:clear 命令時被呼叫:

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->optimizes(
            optimize: 'package:optimize',
            clear: 'package:clear-optimizations',
        );
    }
}

重新載入命令

Laravel 的重新載入命令會終止任何正在運行的服務,以便它們可以由系統進程監視器自動重啟。使用 reloads 方法,您可以註冊套件自己的 Artisan 命令,這些命令應在執行 reload 命令時被呼叫:

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->reloads('package:reload');
    }
}

公開資源

您的套件可能有 JavaScript、CSS 和圖片等資源。要將這些資源發佈到應用程式的 public 目錄,請使用服務提供者的 publishes 方法。在此範例中,我們還將添加一個 public 資源群組標籤,可用於輕鬆發佈相關資源群組:

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    $this->publishes([
        __DIR__.'/../public' => public_path('vendor/courier'),
    ], 'public');
}

現在,當套件使用者執行 vendor:publish 命令時,您的資源將被複製到指定的發佈位置。由於使用者通常需要在每次更新套件時覆蓋資源,因此可以使用 --force 標誌:

php artisan vendor:publish --tag=public --force

發佈檔案群組

您可能希望分別發佈套件資產和資源群組。例如,您可能希望允許使用者發佈套件的配置檔案,而不強制發佈套件的資產。您可以透過在從套件服務提供者呼叫 publishes 方法時對它們進行「標籤」來實現。例如,讓我們使用標籤在套件服務提供者的 boot 方法中為 courier 套件定義兩個發佈群組(courier-configcourier-migrations):

/**
 * 啟動任何套件服務。
 */
public function boot(): void
{
    $this->publishes([
        __DIR__.'/../config/package.php' => config_path('package.php')
    ], 'courier-config');

    $this->publishesMigrations([
        __DIR__.'/../database/migrations/' => database_path('migrations')
    ], 'courier-migrations');
}

現在您的使用者可以在執行 vendor:publish 命令時透過引用其標籤來分別發佈這些群組:

php artisan vendor:publish --tag=courier-config

您的使用者也可以使用 --provider 標誌發佈套件服務提供者定義的所有可發佈檔案:

php artisan vendor:publish --provider="Your\Package\ServiceProvider"