套件開發
簡介
套件是將功能加入 Laravel 的主要方式。套件可以是任何東西,從像 Carbon 這樣出色的日期處理工具,到像 Spatie 的 Laravel Media Library 這樣允許您將檔案與 Eloquent 模型相關聯的套件。
套件有不同類型。某些套件是獨立的,表示它們可以與任何 PHP 框架搭配使用。Carbon 和 Pest 就是獨立套件的範例。您可以在 composer.json
檔案中要求這些套件,以便將其與 Laravel 一起使用。
另一方面,其他套件則是專為與 Laravel 一起使用而設計。這些套件可能具有專為增強 Laravel 應用程式而設計的路由、控制器、視圖和設定。本指南主要涵蓋 Laravel 專用套件的開發。
關於 Facades(外觀模式)的說明
撰寫 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
類別,並包含兩個方法:register
和 boot
。基礎 ServiceProvider
類別位於 illuminate/support
Composer 套件中,您應將其新增至您自己的套件相依性。若要深入瞭解服務提供者的結構和用途,請查看其文件。
資源
設定
通常,您需要將套件的設定檔案發佈到應用程式的 config
目錄。這會允許您的套件使用者輕鬆覆寫您的預設設定選項。若要允許發佈您的設定檔案,請從服務提供者的 boot
方法中呼叫 publishes
方法
/** * Bootstrap any package services. */public function boot(): void{ $this->publishes([ __DIR__.'/../config/courier.php' => config_path('courier.php'), ]);}
現在,當您的套件使用者執行 Laravel 的 vendor:publish
命令時,您的檔案將會被複製到指定的發佈位置。發佈您的設定後,即可像任何其他設定檔案一樣存取其值
$value = config('courier.option');
您不應在設定檔案中定義閉包。當使用者執行 config:cache
Artisan 命令時,它們無法正確序列化。
預設套件設定
您也可以將自己的套件設定檔案與應用程式發佈的副本合併。這將允許您的使用者僅在設定檔案的已發佈副本中定義他們實際想要覆寫的選項。若要合併設定檔案值,請在服務提供者的 register
方法中使用 mergeConfigFrom
方法。
mergeConfigFrom
方法會將套件的設定檔案路徑作為其第一個引數,並將應用程式設定檔案副本的名稱作為其第二個引數
/** * Register any application services. */public function register(): void{ $this->mergeConfigFrom( __DIR__.'/../config/courier.php', 'courier' );}
此方法僅合併設定陣列的第一層。如果您的使用者部分定義多維設定陣列,則不會合併遺失的選項。
路由
如果您的套件包含路由,您可以使用 loadRoutesFrom
方法載入它們。此方法會自動判斷應用程式的路由是否已快取,如果路由已快取,則不會載入您的路由檔案
/** * Bootstrap any package services. */public function boot(): void{ $this->loadRoutesFrom(__DIR__.'/../routes/web.php');}
遷移
如果您的套件包含 資料庫遷移,您可以使用 publishesMigrations
方法告知 Laravel 給定的目錄或檔案包含遷移。當 Laravel 發佈遷移時,它會自動更新其檔案名稱中的時間戳記,以反映目前的日期和時間
/** * Bootstrap any package services. */public function boot(): void{ $this->publishesMigrations([ __DIR__.'/../database/migrations' => database_path('migrations'), ]);}
語言檔案
如果您的套件包含 語言檔案,您可以使用 loadTranslationsFrom
方法告知 Laravel 如何載入它們。例如,如果您的套件名為 courier
,您應該將以下內容新增至服務提供者的 boot
方法
/** * Bootstrap any package services. */public function boot(): void{ $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');}
套件翻譯行會使用 package::file.line
語法慣例來引用。因此,您可以使用以下方式載入 courier
套件 messages
檔案中的 welcome
行
echo trans('courier::messages.welcome');
您可以使用 loadJsonTranslationsFrom
方法為您的套件註冊 JSON 翻譯檔案。此方法接受包含您的套件 JSON 翻譯檔案的目錄路徑。
/** * Bootstrap any package services. */public function boot(): void{ $this->loadJsonTranslationsFrom(__DIR__.'/../lang');}
發布語言檔案
如果您想將套件的語言檔案發布到應用程式的 lang/vendor
目錄,您可以使用服務提供者的 publishes
方法。 publishes
方法接受一個套件路徑及其期望發布位置的陣列。例如,要發布 courier
套件的語言檔案,您可以執行以下操作:
/** * Bootstrap any package services. */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
方法來執行此操作。 loadViewsFrom
方法接受兩個參數:您的視圖範本路徑和您的套件名稱。例如,如果您的套件名稱為 courier
,您應該將以下內容添加到服務提供者的 boot
方法中:
/** * Bootstrap any package services. */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
方法接受一個套件視圖路徑及其期望發布位置的陣列。
/** * Bootstrap the package services. */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; /** * Bootstrap your package's services. */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; /** * Bootstrap your package's services. */public function boot(): void{ Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');}
這將允許使用 package-name::
語法,透過其供應商名稱空間來使用套件元件。
<x-nightshade::calendar /><x-nightshade::color-picker />
Blade 將會透過將元件名稱轉換為帕斯卡命名法(Pascal-casing)來自動偵測連結到此元件的類別。子目錄也支援使用「點」符號。
匿名元件
如果您的套件包含匿名元件,它們必須放置在套件「視圖」目錄(由loadViewsFrom
方法指定)的 components
目錄中。然後,您可以使用套件的視圖名稱空間作為前綴來渲染它們。
<x-courier::alert />
"關於" Artisan 命令
Laravel 內建的 about
Artisan 命令提供了應用程式環境和配置的概要。套件可以透過 AboutCommand
類別將額外資訊推送至此命令的輸出。通常,此資訊可以從您套件服務提供者的 boot
方法中添加。
use Illuminate\Foundation\Console\AboutCommand; /** * Bootstrap any application services. */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; /** * Bootstrap any package services. */public function boot(): void{ if ($this->app->runningInConsole()) { $this->commands([ InstallCommand::class, NetworkCommand::class, ]); }}
最佳化命令
Laravel 的 optimize
命令會快取應用程式的配置、事件、路由和視圖。使用 optimizes
方法,您可以註冊您套件自己的 Artisan 命令,這些命令應該在執行 optimize
和 optimize:clear
命令時被調用。
/** * Bootstrap any package services. */public function boot(): void{ if ($this->app->runningInConsole()) { $this->optimizes( optimize: 'package:optimize', clear: 'package:clear-optimizations', ); }}
公開資源
您的套件可能具有 JavaScript、CSS 和圖片等資源。要將這些資源發佈到應用程式的 public
目錄,請使用服務提供者的 publishes
方法。在此範例中,我們還將添加一個 public
資源群組標籤,該標籤可用於輕鬆發佈相關資源群組。
/** * Bootstrap any package services. */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-config
和 courier-migrations
):
/** * Bootstrap any package services. */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