[TOC]
### **1、簡介**
包是添加功能到?[Laravel](http://laravelacademy.org/tags/laravel "View all posts in Laravel")?的主要方式。包可以提供任何功能,小到處理日期如?[Carbon](https://github.com/briannesbitt/Carbon),大到整個 BDD 測試框架如?[Behat](https://github.com/Behat/Behat)。
當然,有很多不同類型的包。有些包是獨立的,意味著可以在任何框架中使用,而不僅是 Laravel。比如 Carbon 和 Behat 都是獨立的包。所有這些包都可以通過在`composer.json`文件中請求以便被 Laravel 使用。
另一方面,其它包只能特定和 Laravel 一起使用,這些包可能有路由,控制器、視圖和配置用于加強 Laravel 應用的功能,本章主要討論只能在 Laravel 中使用的包。
### **2、服務提供者**
[服務提供者](http://laravelacademy.org/post/2900.html)是包和 Laravel 之間的連接點。服務提供者負責綁定對象到 Laravel 的[服務容器](http://laravelacademy.org/post/2910.html)并告知 Laravel 從哪里加載包資源如視圖、配置和本地化文件。
服務提供者繼承自`Illuminate\Support\ServiceProvider`類并包含兩個方法:`register`和`boot`。`ServiceProvider`基類位于Composer包`illuminate/support`。
要了解更多關于服務提供者的內容,查看其[文檔](http://laravelacademy.org/post/2900.html)。
### **3、路由**
要定義包的路由,只需要在包服務提供者中的`boot`方法中引入路由文件。在路由文件中,可以使用`Route`門面[注冊路由](http://laravelacademy.org/post/2784.html),和Laravel應用中注冊路由一樣:
~~~
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot(){
if (! $this->app->routesAreCached()) {
require __DIR__.'/../../routes.php';
}
}
~~~
### **4、資源**
#### **4.1 視圖**
要在Laravel中注冊包[視圖](http://laravelacademy.org/post/2855.html),需要告訴Laravel視圖在哪,可以使用服務提供者的`loadViewsFrom`方法來實現。`loadViewsFrom`方法接收兩個參數:視圖模板的路徑和包名稱。例如,如果你的包名稱是“courier”,添加如下代碼到服務提供者的`boot`方法:
~~~
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot(){
$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
}
~~~
包視圖通過使用類似的`package::view`語法來引用。所以,你可以通過如下方式加載`courier`包上的`admin`視圖:
~~~
Route::get('admin', function () {
return view('courier::admin');
});
~~~
##### **覆蓋包視圖**
當你使用`loadViewsFrom`方法的時候,Laravel實際上為視圖注冊了兩個存放位置:一個是`resources/views/vendor`目錄,另一個是你指定的目錄。所以,以`courier`為例:當請求一個包視圖時,Laravel首先檢查開發者是否在`resources/views/vendor/courier`提供了自定義版本的視圖,如果該視圖不存在,Laravel才會搜索你調用`loadViewsFrom`方法時指定的目錄。這種機制使得終端用戶可以輕松地自定義/覆蓋包視圖。
##### **發布視圖**
如果你想要視圖能夠發布到應用的`resources/views/vendor`目錄,可以使用服務提供者的`publishes`方法。該方法接收包視圖路徑及其相應的發布路徑數組作為參數:
~~~
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot(){
$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
$this->publishes([
__DIR__.'/path/to/views' => base_path('resources/views/vendor/courier'),
]);
}
~~~
現在,當包用戶執行Laravel的Artisan命令`vendor:publish`時,你的視圖包將會被拷貝到指定路徑。
#### **4.2?翻譯**
如果你的包包含[翻譯文件](http://laravelacademy.org/post/3235.html),你可以使用`loadTranslationsFrom`方法告訴Laravel如何加載它們,例如,如果你的包命名為“courier”,你應該添加如下代碼到服務提供者的`boot`方法:
~~~
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot(){
$this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');
}
~~~
包翻譯使用形如`package::file.line`的語法進行引用。所以,你可以使用如下方式從`messages`文件中加載`courier`包的`welcome`行:
~~~
echo trans('courier::messages.welcome');
~~~
##### **發布翻譯文件**
如果你想要發布包翻譯到應用的resources/lang/vendor目錄,你可以使用服務提供者的publishes方法,該方法接收一個包路徑和相應發布路徑數組參數,例如,要發布courier包的翻譯文件,可以這么做:
~~~
/**
* Perform post-registration booting of services.
*
* @return void
*/public function boot(){
$this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');
$this->publishes([
__DIR__.'/path/to/translations' => resource_path('lang/vendor/courier'),
]);}
~~~
這樣,包用戶可以執行Artisan命令vendor:publish將包翻譯文件發布到應用的指定目錄。
#### **4.3 配置**
通常,你想要發布包配置文件到應用根目錄下的`config`目錄,這將允許包用戶輕松覆蓋默認配置選項,要發布一個配置文件,只需在服務提供者的`boot`方法中使用`publishes`方法即可:
~~~
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot(){
$this->publishes([
__DIR__.'/path/to/config/courier.php' => config_path('courier.php'),
]);
}
~~~
現在,當包用戶執行Laravel的Artisan命令`vendor:publish`時,你的文件將會被拷貝到指定位置,當然,配置被發布后,可以通過和其它配置選項一樣的方式進行訪問:
~~~
$value = config('courier.option');
~~~
##### **默認包配置**
你還可以選擇將自己的包配置文件合并到應用的拷貝版本,這允許用戶只引入他們在應用配置文件中實際想要覆蓋的配置選項。要合并兩個配置,在服務提供者的`register`方法中使用`mergeConfigFrom`方法即可:
~~~
/**
* Register bindings in the container.
*
* @return void
*/
public function register(){
$this->mergeConfigFrom(
__DIR__.'/path/to/config/courier.php', 'courier'
);
}
~~~
### **5、前端資源**
你的包可能包含JavaScript、CSS和圖片,要發布這些前端資源到應用根目錄下的`public`目錄,使用服務提供者的`publishes`方法。在本例中,我們添加一個前端資源組標簽`public`,用于發布相關的前端資源組:
~~~
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot(){
$this->publishes([
__DIR__.'/path/to/assets' => public_path('vendor/courier'),
], 'public');
}
~~~
現在,當包用戶執行`vendor:publish`命令時,前端資源將會被拷貝到指定位置,由于你需要在每次包更新時重寫前端資源,可以使用`--force`標識:
~~~
php artisan vendor:publish --tag=public --force
~~~
如果你想要確保前端資源已經更新到最新版本,可添加該命令到`composer.json`文件的`post-update-cmd`列表。
### **6、發布文件組**
你可能想要分開發布包前端資源組和資源,例如,你可能想要用戶發布包配置的同時不發布包前端資源,可以通過在調用時給它們打上“標簽”來實現分離。下面我們在包服務提供者的`boot`方法中定義兩個公共組:
~~~
/**
* Perform post-registration booting of services.
*
* @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');
}
~~~
現在用戶可以在使用Artisan命令`vendor:publish`時通過引用標簽名來分開發布這兩個組:
~~~
php artisan vendor:publish --provider="Vendor\Providers\PackageServiceProvider" --tag="config"
~~~
- 序言
- 發行版本說明
- 升級指南
- 貢獻代碼
- 開始
- 安裝
- 配置
- Laravel Homestead
- 基礎
- HTTP 路由
- HTTP 中間件
- HTTP 控制器
- HTTP 請求
- HTTP 響應
- 視圖
- Blade 模板引擎
- 架構
- 一次請求的生命周期
- 應用目錄結構
- 服務提供者
- 服務容器
- 門面(Facades)
- 數據庫
- 起步
- 查詢構建器
- 遷移
- 填充數據
- Eloquent ORM
- 起步
- 關聯關系
- 集合
- 訪問器&修改器
- 序列化
- 服務
- 用戶認證
- 用戶授權
- Artisan Console
- 訂閱支付實現:Laravel Cashier
- 緩存
- 集合
- 集成前端資源:Laravel Elixir
- 加密
- 錯誤&日志
- 事件
- 文件系統/云存儲
- 哈希
- 輔助函數
- 本地化
- 郵件
- 包開發
- 分頁
- Redis
- 隊列
- Session
- Envoy Task Runner
- 任務調度
- 測試
- 驗證
- 新手入門指南
- 簡單任務管理系統
- 帶用戶功能的任務管理系統