開(kāi)發(fā)擴(kuò)展包是添加功能到 Laravel 最主要的方法。擴(kuò)展包可以是任何處理日期的方式。例如,Carbon,或是一個(gè)全套的 BDD testing 框架。例如,Behat
當(dāng)然,有非常多不同類型的擴(kuò)展包。有些擴(kuò)展包是獨(dú)立的,意思是此擴(kuò)展包運(yùn)作且兼容于任何的框架,不只有 Laravel。Carbon 以及 Behat 都是這類的擴(kuò)展包。任何這類的擴(kuò)展包只需要在您的composer.json
文件里配置就可以使用。
另一方面,其他的擴(kuò)展包所設(shè)計(jì)的目的是只要在 Laravel 上使用。這些擴(kuò)展包可能包含路由、控制器、視圖以及擴(kuò)展包的相關(guān)配置,目的是為了增加 Laravel 的應(yīng)用。接下來(lái)的說(shuō)明主要涵蓋了 Laravel 開(kāi)發(fā)這些擴(kuò)展包的重點(diǎn)。
所有 Laravel 擴(kuò)展包都發(fā)布到Packagist 以及Composer,所以學(xué)習(xí)這些美好的 PHP 擴(kuò)展包管理工具是必須的。
您擴(kuò)展包內(nèi)部的架構(gòu)全部由您自己規(guī)劃。然而,原則上會(huì)有一個(gè)或更多的服務(wù)提供者. 服務(wù)提供者包含著所有的服務(wù)容器 綁定,也定義了所有您擴(kuò)展包的相關(guān)配置、視圖以及語(yǔ)言文件在什么地方。
擴(kuò)展包的視圖基本上使用兩個(gè)雙冒號(hào)來(lái)指定:
return view('package::view.name');
所有您所要做的只有告訴 Laravel 您所配置擴(kuò)展包名稱視圖的位置在哪里。如果您的擴(kuò)展包取名為 “courier” 您可能需要添加如下到您的服務(wù)提供者的boot
方法:
public function boot()
{
$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
}
現(xiàn)在您可以使用如下的語(yǔ)法來(lái)加載擴(kuò)展包的視圖:
return view('courier::view.name');
當(dāng)您使用loadViewsFrom
方法,Laravel 實(shí)際上為了您的視圖注冊(cè)了兩個(gè)位置。一個(gè)是您應(yīng)用程序的resources/views/vendor
目錄,一個(gè)是您指定的目錄。所以使用我們的例子courier
當(dāng)要求一個(gè)擴(kuò)展包的視圖時(shí),Laravel 會(huì)第一時(shí)間檢查是否有一個(gè)開(kāi)發(fā)者自行自定義在resources/views/vendor/courier
的視圖存在。然而如果還沒(méi)有這個(gè)路徑的視圖被自定義。Laravel 會(huì)搜索您在擴(kuò)展包loadViewsFrom
方法里所指定的視圖。這個(gè)方法讓個(gè)別的用戶可以方便的自定義且覆寫您在擴(kuò)展包里的視圖。
發(fā)布擴(kuò)展包的視圖到resources/views/vendor
目錄,您必須在服務(wù)提供者里的boot
方法里使用publishes
方法:
public function boot()
{
$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
$this->publishes([
__DIR__.'/path/to/views' => base_path('resources/views/vendor/courier'),
]);
}
現(xiàn)在當(dāng)您擴(kuò)展包的用戶使用 Laravel 的命令vendor:publish
您的視圖目錄將會(huì)被復(fù)制到所特定的目錄
如果您想要覆寫已存在的文件,可以使用--force
:
php artisan vendor:publish --force
注意: 您可以使用
publishes
方法,發(fā)布任何您的文件到任何您想要的地方。
擴(kuò)展包的語(yǔ)言文件基本上使用兩個(gè)雙冒號(hào)來(lái)指定:
return trans('package::file.line');
所有您所要做的只有告訴 Laravel 您所配置擴(kuò)展包名稱的語(yǔ)言位置在哪里。如果您的擴(kuò)展包取名為 "courier" 您可能需要添加如下的語(yǔ)法到您的服務(wù)提供者的boot
方法:
public function boot()
{
$this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');
}
注意在您的translations
目錄里,必須要有更下一層的目錄,例如en``es``ru
。
現(xiàn)在您可以使用下方的語(yǔ)法來(lái)加載您擴(kuò)展包的語(yǔ)言:
return trans('courier::file.line');
基本上,您可能想要將您擴(kuò)展包相關(guān)配置的文件發(fā)布到應(yīng)用程序本身的配置目錄config
。這將允許您擴(kuò)展包的用戶簡(jiǎn)單的覆寫這些默認(rèn)的配置文件。
發(fā)布擴(kuò)展包的配置文件只需要在服務(wù)提供者里的boot
方法里使用publishes
方法:
$this->publishes([
__DIR__.'/path/to/config/courier.php' => config_path('courier.php'),
]);
現(xiàn)在當(dāng)擴(kuò)展包的用戶執(zhí)行vendor:publish
命令,您的文件將會(huì)被復(fù)制到特定的位置。當(dāng)然只要配置文件已經(jīng)被發(fā)布,就可以如其他配置文件一樣被訪問(wèn):
$value = config('courier.option');
您可能也選擇想要合并您擴(kuò)展包的配置文件和應(yīng)用程序里的副本配置文件。這允許您的用戶在已經(jīng)被發(fā)布的副本配置文件里只包含任何他們想要覆寫的配置選項(xiàng)。如果想要合并配置文件,可在服務(wù)提供者里的register
方法里使用mergeConfigFrom
方法
$this->mergeConfigFrom(
__DIR__.'/path/to/config/courier.php', 'courier'
);
您的擴(kuò)展包也許會(huì)有一些資源文件比如 JavaScript,CSS,和圖片。如果要發(fā)布資源,可以在您的服務(wù)提供商的boot
方法中使用publishes
方法。在這個(gè)例子中,我們同樣增加了 “public” 資源的分區(qū)標(biāo)記。
$this->publishes([
__DIR__.'/path/to/assets' => public_path('vendor/courier'),
], 'public');
現(xiàn)在當(dāng)擴(kuò)展包的用戶執(zhí)行vendor:publish
命令,您的文件將會(huì)被復(fù)制到特定的位置。由于每次擴(kuò)展更新時(shí)都會(huì)覆蓋這些資源,你可以使用--force
標(biāo)識(shí):
php artisan vendor:publish --tag=public --force
如果你想確保你的公共資源始終是最新的,你可以把這條命名添加到composer.json
文件中的post-update-cmd
列表中。
您可能想要分別的發(fā)布一些分類的文件。舉例,您可能想要您的用戶可以分別發(fā)布擴(kuò)展包的配置文件與靜態(tài)資源文件。您可以使用tagging
來(lái)達(dá)成:
// Publish a config file
$this->publishes([
__DIR__.'/../config/package.php' => config_path('package.php')
], 'config');
// Publish your migrations
$this->publishes([
__DIR__.'/../database/migrations/' => base_path('/database/migrations')
], 'migrations');
您可以使用這些tag
,來(lái)分別發(fā)布這些擴(kuò)展包里的文件。
php artisan vendor:publish --provider="Vendor\Providers\PackageServiceProvider" --tag="config"
在擴(kuò)展包里加載一個(gè)路由文件,只需要在服務(wù)提供者里的boot
方法里使用include
:
public function boot()
{
include __DIR__.'/../../routes.php';
}
注意: 如果您的擴(kuò)展包里使用了控制器,您必須要確認(rèn)您在
composer.json
文件里的 auto-load 區(qū)塊里,是否適當(dāng)?shù)呐渲眠@些控制器。