[Laravel 5] 筆記19 The Service Container

2015-03-18

https://laracasts.com/series/laravel-5-fundamentals/episodes/26

Laravel 會自動判斷對 route 的 closure 參數
或是對應的 controller 的 __construct() 參數
甚或是其中一個 method 的參數
作 injected dependent
如果有找到這一個參數的型別
會自動給出一個這個型別的 instance
▼ app/Http/routes.php

// 這是一個自己建立的 class
class Bar {}

// closure 中
Route::get('foo', function(Bar $bar){
    // 因為有找到 Bar 這個 class 所以會生成一個 instance
    dd($bar);
});


// 或者可以用 bind 的方法
App::bind('Barbar',function(){
    dd('fetching Barbar');
});

// 一樣可以找到
Route::get('foofoo', function(Barbar $barbar){
    dd($barbar);
});

 
另外也可以用 interface 的方法
只要固定傳入這個 interface 型別
之後如果有要修改 只要改這個 interface bind 到的內容即可
▼ app/Http/routes.php

// 這是一個自己建立的 interface
interface BarInterface {}
// 這是一個自己建立的 class implements BarInterface
class Bar implements BarInterface {}
// 另一個自己建立的 class
class SecondBar implements BarInterface {}

// 使用 bind 的方法 連結到 Bar
App::bind('BarInterface','bar');
// 要修改的話 就 bind 到另一個 class SecondBar
App::bind('BarInterface','SecondBar');

// 如果有要修改 injected 的東西 這邊不用改 只要改上面講的 interface bind 的東西就好
Route::get('bar', function(BarInterface $bar){
    dd($bar);
});
// 或者另一個方法
Route::get('bar', function(){
    // 使用 make 取得 BarInterface 的 instance
    $bar = App::make('BarInterface');

    // 下面這 3 個是一樣的意思
    $bar = app->make('BarInterface');
    $bar = app()['BarInterface'];
    $bar = app('BarInterface');

    dd($bar);
});

 
就如同一開始講的
也可以在 Controller 的 __construct() 或是其中一個 method 使用 injection

// 在 __construct() 中可以 injection
class FooController extends Controller {
    private $repository;

    // FooRepository 是一個示範用的 class
    public function __construct(FooRepository $repository)
    {
        $this->repository = $repository;
    }

    public function foo()
    {
        // get() 是示範用的 即 FooRepository 的一個 method
        return $this->repository->get();
    }
}

// 或是只有一個 method 需要的話 寫在 method 裡也可以 injection
class FooController extends Controller {
    public function foo(FooRepository $repository)
    {
        return $repository->get();
    }
}