套件開發
簡介
套件是為 Laravel 新增功能的主要方式。套件可以是任何東西,從處理日期(例如 Carbon)的絕佳方式,到允許您將檔案與 Eloquent 模型關聯的套件,例如 Spatie 的 Laravel Media Library。
套件有不同的類型。有些套件是獨立的,這表示它們可以與任何 PHP 框架協同運作。Carbon 和 Pest 是獨立套件的範例。這些套件中的任何一個都可以透過在您的 composer.json
檔案中要求它們來與 Laravel 一起使用。
另一方面,其他套件專門用於 Laravel。這些套件可能具有路由、控制器、視圖和設定,專門用於增強 Laravel 應用程式。本指南主要涵蓋那些專屬於 Laravel 的套件開發。
關於 Facades 的注意事項
在編寫 Laravel 應用程式時,通常使用 contracts 或 facades 並不重要,因為兩者都提供基本相同的可測試性等級。但是,在編寫套件時,您的套件通常無法存取所有 Laravel 的測試輔助程式。如果您希望能夠像在典型的 Laravel 應用程式內部安裝套件一樣編寫套件測試,則可以使用 Orchestral Testbench 套件。
套件自動探索
Laravel 應用程式的 bootstrap/providers.php
檔案包含應由 Laravel 載入的服務提供者清單。但是,您可以將提供者定義在套件的 composer.json
檔案的 extra
區段中,使其由 Laravel 自動載入,而無需使用者手動將您的服務提供者新增至清單。除了服務提供者之外,您還可以列出任何您想要註冊的 facades
1"extra": { 2 "laravel": { 3 "providers": [ 4 "Barryvdh\\Debugbar\\ServiceProvider" 5 ], 6 "aliases": { 7 "Debugbar": "Barryvdh\\Debugbar\\Facade" 8 } 9 }10},
一旦您的套件已設定為自動探索,Laravel 將在安裝時自動註冊其服務提供者和 facades,為您的套件使用者建立便利的安裝體驗。
選擇退出套件自動探索
如果您是套件的使用者,並且想要停用套件的自動探索,您可以在應用程式的 composer.json
檔案的 extra
區段中列出套件名稱
1"extra": {2 "laravel": {3 "dont-discover": [4 "barryvdh/laravel-debugbar"5 ]6 }7},
您可以使用應用程式的 dont-discover
指令中的 *
字元,停用所有套件的自動探索
1"extra": {2 "laravel": {3 "dont-discover": [4 "*"5 ]6 }7},
服務提供者
服務提供者 是您的套件與 Laravel 之間的連接點。服務提供者負責將事物綁定到 Laravel 的 服務容器 中,並告知 Laravel 在哪裡載入套件資源,例如視圖、設定和語言檔案。
服務提供者擴展了 Illuminate\Support\ServiceProvider
類別,並包含兩個方法:register
和 boot
。基礎 ServiceProvider
類別位於 illuminate/support
Composer 套件中,您應該將其新增至您自己的套件的依賴項。若要深入瞭解服務提供者的結構和目的,請查看 其文件。
資源
設定
通常,您需要將套件的設定檔發佈到應用程式的 config
目錄。這將允許您的套件使用者輕鬆覆寫您的預設設定選項。若要允許發佈您的設定檔,請從您的服務提供者的 boot
方法呼叫 publishes
方法
1/**2 * Bootstrap any package services.3 */4public function boot(): void5{6 $this->publishes([7 __DIR__.'/../config/courier.php' => config_path('courier.php'),8 ]);9}
現在,當您的套件使用者執行 Laravel 的 vendor:publish
命令時,您的檔案將被複製到指定的發佈位置。一旦您的設定已發佈,就可以像任何其他設定檔一樣存取其值
1$value = config('courier.option');
您不應在設定檔中定義 closures。當使用者執行 config:cache
Artisan 命令時,它們無法正確序列化。
預設套件設定
您也可以將您自己的套件設定檔與應用程式的已發佈副本合併。這將允許您的使用者僅定義他們實際想要在設定檔的已發佈副本中覆寫的選項。若要合併設定檔值,請在服務提供者的 register
方法中使用 mergeConfigFrom
方法。
mergeConfigFrom
方法接受您的套件設定檔的路徑作為其第一個引數,並接受應用程式的設定檔副本的名稱作為其第二個引數
1/**2 * Register any application services.3 */4public function register(): void5{6 $this->mergeConfigFrom(7 __DIR__.'/../config/courier.php', 'courier'8 );9}
此方法僅合併設定陣列的第一層。如果您的使用者部分定義了多維設定陣列,則遺失的選項將不會被合併。
路由
如果您的套件包含路由,您可以使用 loadRoutesFrom
方法載入它們。此方法將自動判斷應用程式的路由是否已快取,如果路由已快取,則不會載入您的路由檔案
1/**2 * Bootstrap any package services.3 */4public function boot(): void5{6 $this->loadRoutesFrom(__DIR__.'/../routes/web.php');7}
遷移
如果您的套件包含 資料庫遷移,您可以使用 publishesMigrations
方法告知 Laravel 給定的目錄或檔案包含遷移。當 Laravel 發佈遷移時,它將自動更新其檔案名稱中的時間戳記,以反映目前的日期和時間
1/**2 * Bootstrap any package services.3 */4public function boot(): void5{6 $this->publishesMigrations([7 __DIR__.'/../database/migrations' => database_path('migrations'),8 ]);9}
語言檔案
如果您的套件包含 語言檔案,您可以使用 loadTranslationsFrom
方法告知 Laravel 如何載入它們。例如,如果您的套件名為 courier
,您應該將以下內容新增至您的服務提供者的 boot
方法
1/**2 * Bootstrap any package services.3 */4public function boot(): void5{6 $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');7}
套件翻譯行使用 package::file.line
語法慣例引用。因此,您可以像這樣從 messages
檔案載入 courier
套件的 welcome
行
1echo trans('courier::messages.welcome');
您可以使用 loadJsonTranslationsFrom
方法為您的套件註冊 JSON 翻譯檔案。此方法接受包含您的套件 JSON 翻譯檔案的目錄路徑
1/**2 * Bootstrap any package services.3 */4public function boot(): void5{6 $this->loadJsonTranslationsFrom(__DIR__.'/../lang');7}
發佈語言檔案
如果您想要將套件的語言檔案發佈到應用程式的 lang/vendor
目錄,您可以使用服務提供者的 publishes
方法。publishes
方法接受套件路徑陣列及其所需的發佈位置。例如,若要發佈 courier
套件的語言檔案,您可以執行以下操作
1/** 2 * Bootstrap any package services. 3 */ 4public function boot(): void 5{ 6 $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier'); 7 8 $this->publishes([ 9 __DIR__.'/../lang' => $this->app->langPath('vendor/courier'),10 ]);11}
現在,當您的套件使用者執行 Laravel 的 vendor:publish
Artisan 命令時,您的套件的語言檔案將發佈到指定的發佈位置。
視圖
若要向 Laravel 註冊套件的 視圖,您需要告訴 Laravel 視圖位於何處。您可以使用服務提供者的 loadViewsFrom
方法來執行此操作。loadViewsFrom
方法接受兩個引數:您的視圖範本的路徑和您的套件名稱。例如,如果您的套件名稱為 courier
,您會將以下內容新增至您的服務提供者的 boot
方法
1/**2 * Bootstrap any package services.3 */4public function boot(): void5{6 $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');7}
套件視圖使用 package::view
語法慣例引用。因此,一旦您的視圖路徑在服務提供者中註冊,您就可以像這樣從 courier
套件載入 dashboard
視圖
1Route::get('/dashboard', function () {2 return view('courier::dashboard');3});
覆寫套件視圖
當您使用 loadViewsFrom
方法時,Laravel 實際上會為您的視圖註冊兩個位置:應用程式的 resources/views/vendor
目錄和您指定的目錄。因此,以 courier
套件為例,Laravel 將首先檢查開發人員是否已將自訂版本的視圖放置在 resources/views/vendor/courier
目錄中。然後,如果視圖尚未自訂,Laravel 將搜尋您在呼叫 loadViewsFrom
時指定的套件視圖目錄。這使得套件使用者可以輕鬆自訂/覆寫您的套件視圖。
發佈視圖
如果您想要讓您的視圖可發佈到應用程式的 resources/views/vendor
目錄,您可以使用服務提供者的 publishes
方法。publishes
方法接受套件視圖路徑陣列及其所需的發佈位置
1/** 2 * Bootstrap the package services. 3 */ 4public function boot(): void 5{ 6 $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier'); 7 8 $this->publishes([ 9 __DIR__.'/../resources/views' => resource_path('views/vendor/courier'),10 ]);11}
現在,當您的套件使用者執行 Laravel 的 vendor:publish
Artisan 命令時,您的套件的視圖將被複製到指定的發佈位置。
視圖組件
如果您正在建構使用 Blade 組件或將組件放置在非傳統目錄中的套件,您需要手動註冊您的組件類別及其 HTML 標籤別名,以便 Laravel 知道在哪裡找到該組件。您通常應該在套件服務提供者的 boot
方法中註冊您的組件
1use Illuminate\Support\Facades\Blade; 2use VendorPackage\View\Components\AlertComponent; 3 4/** 5 * Bootstrap your package's services. 6 */ 7public function boot(): void 8{ 9 Blade::component('package-alert', AlertComponent::class);10}
一旦您的組件已註冊,就可以使用其標籤別名來呈現它
1<x-package-alert/>
自動載入套件組件
或者,您可以使用 componentNamespace
方法依慣例自動載入組件類別。例如,Nightshade
套件可能具有 Calendar
和 ColorPicker
組件,這些組件位於 Nightshade\Views\Components
命名空間內
1use Illuminate\Support\Facades\Blade;2 3/**4 * Bootstrap your package's services.5 */6public function boot(): void7{8 Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');9}
這將允許使用套件組件,方法是透過其供應商命名空間,使用 package-name::
語法
1<x-nightshade::calendar />2<x-nightshade::color-picker />
Blade 將透過將組件名稱轉換為 Pascal 大小寫,自動偵測連結到此組件的類別。也支援使用「點」表示法的子目錄。
匿名組件
如果您的套件包含匿名組件,它們必須放置在套件「視圖」目錄的 components
目錄中(如 loadViewsFrom
方法 所指定)。然後,您可以透過在組件名稱前加上套件的視圖命名空間來呈現它們
1<x-courier::alert />
「About」Artisan 命令
Laravel 內建的 about
Artisan 命令提供了應用程式環境和設定的概要。套件可以透過 AboutCommand
類別將其他資訊推送至此命令的輸出。通常,此資訊可以從您的套件服務提供者的 boot
方法新增
1use Illuminate\Foundation\Console\AboutCommand;2 3/**4 * Bootstrap any application services.5 */6public function boot(): void7{8 AboutCommand::add('My Package', fn () => ['Version' => '1.0.0']);9}
命令
若要向 Laravel 註冊您的套件的 Artisan 命令,您可以使用 commands
方法。此方法預期命令類別名稱的陣列。一旦命令已註冊,您就可以使用 Artisan CLI 執行它們
1use Courier\Console\Commands\InstallCommand; 2use Courier\Console\Commands\NetworkCommand; 3 4/** 5 * Bootstrap any package services. 6 */ 7public function boot(): void 8{ 9 if ($this->app->runningInConsole()) {10 $this->commands([11 InstallCommand::class,12 NetworkCommand::class,13 ]);14 }15}
最佳化命令
Laravel 的 optimize
命令 快取應用程式的設定、事件、路由和視圖。使用 optimizes
方法,您可以註冊您自己的套件 Artisan 命令,這些命令應在執行 optimize
和 optimize:clear
命令時調用
1/** 2 * Bootstrap any package services. 3 */ 4public function boot(): void 5{ 6 if ($this->app->runningInConsole()) { 7 $this->optimizes( 8 optimize: 'package:optimize', 9 clear: 'package:clear-optimizations',10 );11 }12}
公開資源
您的套件可能具有資源,例如 JavaScript、CSS 和圖片。若要將這些資源發佈到應用程式的 public
目錄,請使用服務提供者的 publishes
方法。在此範例中,我們也將新增 public
資源群組標籤,可用於輕鬆發佈相關資源群組
1/**2 * Bootstrap any package services.3 */4public function boot(): void5{6 $this->publishes([7 __DIR__.'/../public' => public_path('vendor/courier'),8 ], 'public');9}
現在,當您的套件使用者執行 vendor:publish
命令時,您的資源將被複製到指定的發佈位置。由於使用者通常需要在每次更新套件時覆寫資源,因此您可以使用 --force
旗標
1php artisan vendor:publish --tag=public --force
發佈檔案群組
您可能想要分別發佈套件資源和資源群組。例如,您可能想要允許使用者發佈您的套件設定檔,而無需強制發佈您的套件資源。您可以透過在從套件服務提供者呼叫 publishes
方法時「標記」它們來執行此操作。例如,讓我們在套件服務提供者的 boot
方法中使用標籤來定義 courier
套件的兩個發佈群組(courier-config
和 courier-migrations
)
1/** 2 * Bootstrap any package services. 3 */ 4public function boot(): void 5{ 6 $this->publishes([ 7 __DIR__.'/../config/package.php' => config_path('package.php') 8 ], 'courier-config'); 9 10 $this->publishesMigrations([11 __DIR__.'/../database/migrations/' => database_path('migrations')12 ], 'courier-migrations');13}
現在,您的使用者可以透過在執行 vendor:publish
命令時參考其標籤來分別發佈這些群組
1php artisan vendor:publish --tag=courier-config