Service provider最主要的功能就是讓我們寫package,本文一步一步的介紹
實際寫過package之後,會讓我們對service provider與composer有更深刻的了解。
最簡單
的package,僅有Hello World
的功能,並包含route、controller與view,然後打包成package送上Github與Packagist,最後另外開一個專案,使用composer require
下載,執行我們自己上傳的package。實際寫過package之後,會讓我們對service provider與composer有更深刻的了解。
Version
Laravel 5.1
建立Laravel專案
1
| oomusou@mac:~$ composer create-project laravel/laravel MyPackage --prefer-dist
|
建立開發package用的專案。
建立目錄
在專案
在
根目錄
下建立packages
目錄,我們所有的package source code都會放這裡。在
packages
目錄下建立vendor/package/src
子目錄,本範例會建立oomusou/helloworld/src
。1 1vendor與package名稱建議都小寫,且可以相同,如laravel/laravel
,也可以不同,如Jeffery Way的Generators是way/generators
。建立composer.json
每個package都必須有composer.json,用來描述其使用的
相依套件
與namespace
。進入packages/oomusou/helloworld
目錄 :1
| oomusou@mac:~/MyPackage/packages/oomusou/helloworld$ composer init
|
所有問題皆按
Enter
即可,會產生一個預設的composer.json
。1 2 3 4 5 6 7 8 9 10 | { "name": "oomusou/helloworld", "authors": [ { "name": "oomusou", "email": "oomusou@gmail.com" } ], "require": {} } |
設定PSR-4命名空間
由於目前Laravel預設的
root namespace
是在app
目錄下,並無法得知新加的package/oomusou/helloworld/src
目錄,必須在MyPackage
專案的composer.json
加入新的root namespace
。2 2注意是MyPackage
專案的composer.json
,不是
剛剛在packages/oomusou/helloworld
目錄下建立的composer.json
。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | { "name": "laravel/laravel", "description": "The Laravel Framework.", "keywords": ["framework", "laravel"], (略) "autoload": { "classmap": [ "database" ], "psr-4": { "App\\": "app/", "Oomusou\\HelloWorld\\": "packages/oomusou/helloworld/src/" } }, (略) } |
12行
1
| "Oomusou\\Helloworld\\": "packages/oomusou/helloworld/src/"
|
加入新的namespace :
Oomusou\HelloWorld
。
產生新的autoload檔案3 3注意是
MyPackage
專案目錄下產生autoload檔案,不是
剛剛的packages/oomusou/helloworld
目錄下。1
| oomusou@mac:~/MyPackage$ composer dump-autoload
|
建立Service Provider
1
| oomusou@mac:~/MyPackage$ php artisan make:provider HelloWorldServiceProvider
|
產生
HelloWorldServiceProvider.php
在app/Providers
目錄下,因為我們是要寫package,所以將此檔案移到packages/oomusou/helloworld/src
目錄下。
因為目錄已經移動,需要重新修改namespace。4 4Namespace建議遵循PSR-2規範,使用
CamelCase
,詳細請參考PSR-1 & PSR-2 PHP Coding Style1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | namespace Oomusou\HelloWorld; use Illuminate\Support\ServiceProvider; class HelloWorldServiceProvider extends ServiceProvider { /** * Bootstrap the application services. * * @return void */ public function boot() { // } /** * Register the application services. * * @return void */ public function register() { // } } |
預設會建立
boot()
與register()
。55關於boot()
與register()
的意義與差異,詳細請參考深入探討Service Provider
在
config/app.php
中註冊HelloWorldServiceProvider
。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | return [ (略) 'providers' => [ /* * Laravel Framework Service Providers... */ Illuminate\Foundation\Providers\ArtisanServiceProvider::class, (略) Illuminate\View\ViewServiceProvider::class, Oomusou\HelloWorld\HelloWorldServiceProvider::class, /* * Application Service Providers... */ App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, ], (略) ]; |
12行
1
| oomusou\helloworld\HelloWorldServiceProvider::class,
|
註冊剛剛建立的
HelloWorldServiceProvider
。建立Controller
1
| oomusou@mac:~/MyPackage$ php artisan make:controller HelloWorldController
|
產生
HelloWorldController
在app/Http/Controllers
目錄下,因為我們是要寫package,所以將此檔案移到packages/oomusou/helloworld/src
目錄下。
因為目錄已經移動,須重新修改namespace,並且只留下
index()
。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | namespace Oomusou\HelloWorld; use App\Http\Controllers\Controller; use App\Http\Requests; class HelloWorldController extends Controller { /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { $message = 'Hello World'; return view('HelloWorld::welcome', compact('message')); } } |
建立
$message
變數,並顯示welcome.blade.php
。HelloWorld::welcome
表示welcome
在HelloWorld
的namespace下,稍後會指定。建立Route
將
app/Http/routes.php
複製到packages/oomusou/helloworld/src
。1
| Route::get('helloworld', 'Oomusou\HelloWorld\HelloWorldController@index');
|
將URI為
helloworld
時,使用HelloWorldController
的index
。建立View
在此不用特別建立view,先在
packages/oomusou/helloworld/src
建立views
目錄,並將Laravel 5.1預設的resources/views/welcome.blade.php
複製到package/oomusou/helloworld/src/views
目錄下。
將Laravel 5改成{{$message}}。
修改Service Provider
之前都沒使用到service provider的
boot()
,現在要正式使用了。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | namespace Oomusou\HelloWorld; use Illuminate\Support\ServiceProvider; class HelloWorldServiceProvider extends ServiceProvider { /** * Bootstrap the application services. * * @return void */ public function boot() { $this->app->make(HelloWorldController::class); include(__DIR__ . '/routes.php'); $this->loadViewsFrom(__DIR__ . '/views', 'HelloWorld'); } /** * Register the application services. * * @return void */ public function register() { // } } |
13行
1 2 3 4 5 6 7 8 | public function boot() { $this->app->make(HelloWorldController::class); include(__DIR__ . '/routes.php'); $this->loadViewsFrom(__DIR__ . '/views', 'HelloWorld'); } |
- 由
$this->app->make()
建立HelloWorldController
。 - 其中
__DIR__
會傳回HelloWorldServiceProvider.php
的目錄路徑,也就是packages/oomusou/helloworld/src
,將routes.php
include進來,使專案會用到package的route。 - 使用
loadViewsFrom()
,第1個參數傳入package的view的目錄位置,第2個參數為view的namespace。
至於
register()
,因為這個範例都沒使用到service container,所以不用寫任何code。測試Package
上傳Github
設定命名空間
目前package由於是搭配
MyPackage
專案測試,所以將PSR-4的root namespace設定在MyPackage
專案的composer.json
,但發佈package之後,不可能要user也手動在composer.json
加上namespace,所以我們要將namespace設定在package自己的composer.json
。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | { "name": "oomusou/helloworld", "authors": [ { "name": "oomusou", "email": "oomusou@gmail.com" } ], "require": {}, "autoload": { "psr-4": { "Oomusou\\HelloWorld\\": "src/" } } } |
建立本地git倉儲
1
| oomusou@mac:~/MyPackage$ cd packages/oomusou/helloworld
oomusou@mac:~/MyPackage/packages/oomusou/helloworld$ git init
oomusou@mac:~/MyPackage/packages/oomusou/helloworld$ git add .
oomusou@mac:~/MyPackage/packages/oomusou/helloworld$ git commit -m "Initial commit."
|
建立遠端git倉儲
Push至Github
1
| oomusou@mac:~/MyPackage/packages/oomusou/helloworld$ git remote add origin git@github.com:oomusou/helloworld.git
oomusou@mac:~/MyPackage/packages/oomusou/helloworld$ git push -u origin master
oomusou@mac:~/MyPackage/packages/oomusou/helloworld$ git tag -a 1.0.0 -m "First version"
oomusou@mac:~/MyPackage/packages/oomusou/helloworld$ git push --tags
|
其中下tag是必須的,否則composer安裝package時,會要求你設定
minimum-stability
。上傳Packagist
登入Packagist
提交Github網址
確認提交
上傳成功
測試Package
建立測試專案
1
| oomusou@mac:~$ composer create-project laravel/laravel MyTestPackage --prefer-dist
|
建立開發測試package用的專案。
安裝Package
1
| oomusou@mac:~$ cd MyTestPackage
oomusou@mac:~/MyTestPackage$ composer require oomusou/helloworld
|
註冊Service Provider
在
config/app.php
中註冊HelloWorldServiceProvider
。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | return [ (略) 'providers' => [ /* * Laravel Framework Service Providers... */ Illuminate\Foundation\Providers\ArtisanServiceProvider::class, (略) Illuminate\View\ViewServiceProvider::class, Oomusou\HelloWorld\HelloWorldServiceProvider::class, /* * Application Service Providers... */ App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, ], (略) ]; |
12行
1
| oomusou\helloworld\HelloWorldServiceProvider::class,
|
註冊剛剛建立的
HelloWorldServiceProvider
。瀏覽器測試
Conclusion
- Package開發牽涉到對service provider與composer的了解,還要搭配Git與Github操作,只要一個環節出錯,整個開發過程就會失敗。
- 與商業邏輯無關,且可以重複使用的部分,可以考慮寫成package,以加速團隊開發流程。
- 寫package與寫testing一樣有趣,一旦迷上了就很難戒掉 XDD
Sample Code
完整的範例可以在我的GitHub上找到。
from : http://oomusou.io/laravel/laravel-package-hello-world/
沒有留言:
張貼留言