擴(kuò)展包開(kāi)發(fā)
擴(kuò)展包開(kāi)發(fā)
擴(kuò)展包開(kāi)發(fā)
簡(jiǎn)介
擴(kuò)展包是向 Laravel 中添加功能的主要方式。擴(kuò)展包可以包含很多有用的功能,例如時(shí)間處理擴(kuò)展包 Carbon,或提供完整 BDD 測(cè)試框架的擴(kuò)展包 Behat。
當(dāng)然,擴(kuò)展包有很多種類(lèi)型。有些擴(kuò)展包是獨(dú)立運(yùn)行的,意味著他們可以在任意的 PHP 框架中使用。Carbon 和 Behat 就是這樣的獨(dú)立擴(kuò)展包。要在 Laravel 中使用這種擴(kuò)展包只需要在 composer.json
文件中引入他們即可。
另一方面,有些擴(kuò)展包只能在 Laravel 中使用。這些擴(kuò)展包可能包含專(zhuān)門(mén)用來(lái)增強(qiáng) Laravel 應(yīng)用的路由、控制器、視圖和配置的文件。這份指南主要介紹 Laravel 擴(kuò)展包的開(kāi)發(fā)。
Facades 注解
當(dāng)開(kāi)發(fā) Laravel 應(yīng)用時(shí),通常使用契約(contracts)或 facades 沒(méi)有什么區(qū)別,因?yàn)樗麄兌继峁┗鞠嗤目蓽y(cè)試能力。然而,在進(jìn)行擴(kuò)展包開(kāi)發(fā)的時(shí)候,擴(kuò)展包并不能訪(fǎng)問(wèn) Laravel 提供的所有測(cè)試輔助函數(shù)。如果你想像在 Laravel 應(yīng)用中一樣編寫(xiě)擴(kuò)展包的測(cè)試用例,你可以使用擴(kuò)展包 Orchestral Testbench。
發(fā)現(xiàn)擴(kuò)展包
在 Laravel 應(yīng)用的 config/app.php
配置文件中,providers
選項(xiàng)定義了能夠被 Laravel 加載的服務(wù)提供者列表。當(dāng)有人安裝你的擴(kuò)展包時(shí),你需要將你的服務(wù)提供者包含到這個(gè)列表中。你可以將服務(wù)提供者定義到擴(kuò)展包的 composer.json
文件中的 extra
部分,而不是讓用戶(hù)手動(dòng)將你的服務(wù)提供者添加到列表中。除了服務(wù)提供者,還可以列出所有你想注冊(cè)的 facades:
"extra": { "laravel": { "providers": [ "Barryvdh\\Debugbar\\ServiceProvider" ], "aliases": { "Debugbar": "Barryvdh\\Debugbar\\Facade" } } },
一旦你的擴(kuò)展包配置為可發(fā)現(xiàn),Laravel 就會(huì)在安裝時(shí)自動(dòng)注冊(cè)擴(kuò)展包的服務(wù)提供者和 facades,為擴(kuò)展包的用戶(hù)提供一個(gè)友好的安裝體驗(yàn)。
選擇性的發(fā)現(xiàn)擴(kuò)展包
如果你是擴(kuò)展包的用戶(hù),想要禁止一個(gè)擴(kuò)展包被發(fā)現(xiàn),你可以在應(yīng)用的 composer.json
文件中的 extra
部分列出這個(gè)擴(kuò)展包:
"extra": { "laravel": { "dont-discover": [ "barryvdh/laravel-debugbar" ] } },
你也可以通過(guò)在應(yīng)用的 dont-discover
指令中使用 *
字符,禁用擴(kuò)展包發(fā)現(xiàn)功能:
"extra": { "laravel": { "dont-discover": [ "*" ] } },
服務(wù)提供者
服務(wù)提供者 讓你的擴(kuò)展包與 Laravel 聯(lián)系在一起。服務(wù)提供者負(fù)責(zé)將一些東西綁定到 Laravel 的 服務(wù)容器 中,并且告訴 Laravel 從哪里加載擴(kuò)展包的資源文件,例如視圖、配置文件、語(yǔ)言包等。
服務(wù)提供者繼承了 Illuminate\Support\ServiceProvider
類(lèi),并包含了兩個(gè)方法:register
和 boot
?;?lèi) ServiceProvider
位于名為 illuminate/support
的 Composer 擴(kuò)展包中,你必須將它加入到你的擴(kuò)展包依賴(lài)。想要了解更多關(guān)于服務(wù)提供者的結(jié)構(gòu)和用途,請(qǐng)查閱 它的文檔.
資源文件
配置
有時(shí),你需要將擴(kuò)展包配置文件發(fā)布到應(yīng)用本身的 config
目錄中。這樣使用擴(kuò)展包的用戶(hù)就可以輕松的重寫(xiě)默認(rèn)配置項(xiàng)。想要發(fā)布擴(kuò)展包配置文件,只需要在服務(wù)提供者的 boot
方法中調(diào)用 publishes
方法即可:
/** * 在注冊(cè)后啟動(dòng)服務(wù)。 * * @return void */ public function boot(){ $this->publishes([ __DIR__.'/path/to/config/courier.php' => config_path('courier.php'), ]); }
現(xiàn)在,當(dāng)擴(kuò)展包的用戶(hù)執(zhí)行 Laravel 的 vendor:publish
命令,擴(kuò)展包文件就會(huì)被復(fù)制到指定的目錄中。當(dāng)然,一旦你的配置文件被發(fā)布,就可以如同其他配置一樣被訪(fǎng)問(wèn):
$value = config('courier.option');
{note} 你不應(yīng)該在配置文件中定義閉包函數(shù)。因?yàn)楫?dāng)用戶(hù)執(zhí)行
config:cache
Artisan 命令時(shí),配置文件將不能被正確的序列化。
擴(kuò)展包默認(rèn)配置
你也可以將擴(kuò)展包默認(rèn)配置與應(yīng)用的副本配置合并在一起。這樣擴(kuò)展包用戶(hù)就可以在副本配置文件中定義他們想要覆蓋的配置選項(xiàng)。想要合并配置,只需要在服務(wù)提供者的 register
方法中調(diào)用 mergeConfigFrom
方法即可:
/** * 在容器中注冊(cè)綁定。 * * @return void */ public function register(){ $this->mergeConfigFrom( __DIR__.'/path/to/config/courier.php', 'courier' ); }
{note} 此方法只合并配置數(shù)組的第一維。如果擴(kuò)展包用戶(hù)定義了多維配置數(shù)組,缺少的選項(xiàng)將不會(huì)被合并。
路由
如果你的擴(kuò)展包中包含路由文件,你需要使用 loadRoutesFrom
方法加載他們。此方法將自動(dòng)判斷應(yīng)用的路由是否已被緩存,如果路由已緩存,將不會(huì)加載你的路由文件:
/** * 在注冊(cè)后啟動(dòng)服務(wù)。 * * @return void */ public function boot(){ $this->loadRoutesFrom(__DIR__.'/routes.php'); }
數(shù)據(jù)庫(kù)遷移
如果你的擴(kuò)展包中包含 數(shù)據(jù)庫(kù)遷移,你需要使用 loadMigrationsFrom
方法告知 Laravel 如何加載他們。loadMigrationsFrom
方法只需要擴(kuò)展包遷移文件路徑作為唯一參數(shù):
/** * 在注冊(cè)后啟動(dòng)服務(wù)。 * * @return void */ public function boot(){ $this->loadMigrationsFrom(__DIR__.'/path/to/migrations'); }
一旦你的擴(kuò)展包遷移文件被注冊(cè),當(dāng)運(yùn)行 php artisan migrate
命令時(shí)他們就會(huì)被自動(dòng)執(zhí)行。你不需要將他們導(dǎo)入到應(yīng)用的 database/migrations
目錄中。
語(yǔ)言包
如果你的擴(kuò)展包中包含 語(yǔ)言包文件,你需要使用 loadTranslationsFrom
方法告知 Laravel 如何加載他們。例如,如果你的擴(kuò)展包名為 courier
,你需要將下面的內(nèi)容加入到服務(wù)提供者的 boot
方法中:
/** * 在注冊(cè)后啟動(dòng)服務(wù)。 * * @return void */ public function boot(){ $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier'); }
擴(kuò)展包翻譯約定使用 package::file.line
語(yǔ)法進(jìn)行引用。因此,你可以按照下面的方式來(lái)加載 courier
擴(kuò)展包中的 messages
文件的 welcome
行:
echo trans('courier::messages.welcome');
發(fā)布語(yǔ)言包
如果你想要將擴(kuò)展包中的語(yǔ)言包發(fā)布到應(yīng)用的 resources/lang/vendor
目錄,可以使用服務(wù)提供者的 publishes
方法。publishes
方法接收一個(gè)包含語(yǔ)言包路徑和對(duì)應(yīng)發(fā)布位置的數(shù)組。例如,發(fā)布 courier
擴(kuò)展包的語(yǔ)言包文件,操作如下:
/** * 在注冊(cè)后啟動(dòng)服務(wù)。 * * @return void */ public function boot(){ $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier'); $this->publishes([ __DIR__.'/path/to/translations' => resource_path('lang/vendor/courier'), ]); }
現(xiàn)在,當(dāng)擴(kuò)展包的用戶(hù)執(zhí)行 Laravel 的 vendor:publish
Artisan 命令,語(yǔ)言包將會(huì)被發(fā)布到指定的目錄中。
視圖
想要在 Laravel 中注冊(cè)你的擴(kuò)展包的 視圖, 需要告知 Laravel 視圖文件的位置。你可以使用服務(wù)提供者的 loadViewsFrom
方法來(lái)實(shí)現(xiàn)。loadViewsFrom
方法允許接收兩個(gè)參數(shù):視圖模板路徑和擴(kuò)展包名。例如,如果你的擴(kuò)展包名為 courier
,你需要將下面的內(nèi)容加入到服務(wù)提供者的 boot
方法中:
/** * 在注冊(cè)后啟動(dòng)服務(wù)。 * * @return void */ public function boot(){ $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier'); }
擴(kuò)展包視圖約定使用 package::view
語(yǔ)法進(jìn)行引用。因此,一旦視圖路徑在服務(wù)提供者中注冊(cè)成功,你可以使用下面的方式來(lái)加載 courier
擴(kuò)展包中的 admin
視圖:
Route::get('admin', function () { return view('courier::admin'); });
重寫(xiě)擴(kuò)展包視圖
當(dāng)你使用 loadViewsFrom
方法時(shí),Laravel 實(shí)際上在兩個(gè)位置注冊(cè)視圖:應(yīng)用的 resources/views/vendor
目錄和你的自定義目錄。所以,還以 courier
擴(kuò)展包為例,Laravel 首先會(huì)檢查開(kāi)發(fā)人員是否在 resources/views/vendor/courier
中提供了一個(gè)自定義版本的視圖。然后,如果視圖尚未被定義,Laravel 將會(huì)搜索在 loadViewsFrom
中定義的視圖目錄。這種方法可以讓用戶(hù)很簡(jiǎn)單的自定義或重寫(xiě)擴(kuò)展包的視圖。
發(fā)布視圖
如果你希望將你的視圖發(fā)布到應(yīng)用的 resources/views/vendor
目錄中,可以使用服務(wù)提供者的 publishes
方法。publishes
方法接收一個(gè)包含視圖路徑和對(duì)應(yīng)發(fā)布位置的數(shù)組:
/** * 在注冊(cè)后啟動(dòng)服務(wù)。 * * @return void */ public function boot(){ $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier'); $this->publishes([ __DIR__.'/path/to/views' => resource_path('views/vendor/courier'), ]); }
現(xiàn)在,當(dāng)擴(kuò)展包的用戶(hù)執(zhí)行 Laravel 的 vendor:publish
Artisan 命令,視圖將會(huì)被發(fā)布到自定的目錄中。
命令
想要在 Laravel 中注冊(cè)擴(kuò)展包的 Artisan 命令,需要使用 commands
方法。此方法接收一個(gè)命令類(lèi)的數(shù)組。一旦這些命令注冊(cè)成功,可以使用 Artisan 命令行 執(zhí)行他們:
/** * 引導(dǎo)應(yīng)用服務(wù)。 * * @return void */ public function boot(){ if ($this->app->runningInConsole()) { $this->commands([ FooCommand::class, BarCommand::class, ]); } }
公共資源文件
你的擴(kuò)展包中可能存在 JavaScript、CSS 和圖片之類(lèi)的資源文件。想要發(fā)布這些資源文件到應(yīng)用的 public
目錄,可以使用服務(wù)提供者的 publishes
方法。在下面的例子中,我們也可以添加一個(gè) public
資源分類(lèi)標(biāo)簽,可用于相關(guān)發(fā)布資源的分類(lèi):
/** * 在注冊(cè)后啟動(dòng)服務(wù)。 * * @return void */ public function boot(){ $this->publishes([ __DIR__.'/path/to/assets' => public_path('vendor/courier'), ], 'public'); }
現(xiàn)在,當(dāng)擴(kuò)展包的用戶(hù)執(zhí)行 vendor:publish
命令,你的資源文件將會(huì)被復(fù)制到指定的目錄中。由于每次更新擴(kuò)展包時(shí)通常都需要覆蓋資源文件,因此需要使用 --force
標(biāo)簽:
php artisan vendor:publish --tag=public --force
發(fā)布群組文件
你可能想要分別打包發(fā)布擴(kuò)展包資源文件或資源。舉個(gè)例子,你想讓用戶(hù)單獨(dú)發(fā)布擴(kuò)展包中的配置文件,而不是被強(qiáng)制發(fā)布擴(kuò)展包中的所有資源文件。你可以通過(guò)調(diào)用擴(kuò)展包服務(wù)提供者中的 publishes
方法給不同文件打上「標(biāo)簽」。例如,讓我們使用擴(kuò)展包服務(wù)提供者中的 boot
方法來(lái)定義兩個(gè)發(fā)布群組:
/** * 在注冊(cè)后啟動(dòng)服務(wù)。 * * @return void */ public function boot(){ $this->publishes([ __DIR__.'/../config/package.php' => config_path('package.php') ], 'config'); $this->publishes([ __DIR__.'/../database/migrations/' => database_path('migrations') ], 'migrations'); }
現(xiàn)在你的用戶(hù)就可以通過(guò)執(zhí)行 vendor:publish
命令,根據(jù)定義的標(biāo)簽來(lái)發(fā)布不同的群組文件:
php artisan vendor:publish --tag=config