Laravel 服務容器、服務提供器、契約例項講解

xiaocailc發表於2018-09-26

前言

剛開始看laravel服務容器、契約、服務提供器的確生澀難懂,不單單是概念繁多,而且實際的demo很難找(找是找到了,但難用啊),最後就隔一段時間看一遍,大概個十來遍,還真給看出個門道,廢話少說上程式碼。

準備階段

首先宣告一下我的測試環境
php 7.2.4
laravel 5.6

1.建立新專案(composer)

在你的專案目錄命令列執行:

composer create-project laravel/laravel laravelapp --prefer-dist

2.建立服務提供器

生成檔案位於:專案/app/Providers/TestServiceProvider

php artisan make:provider TestServiceProvider

同時修改配置檔案config/app.php,在providers陣列中追加該服務提供器

'providers' => [
     App\Providers\TestServiceProvider::class,
],

3.建立自己的工作目錄(xiaocai)

我的工作目錄在:專案/app/Xiaocai目錄下

// 目錄結構  
|---app  
     |---Xiaocai    
         |---Test  
            |---DemoInterface.php  
            |---DemoProvider.php  
            |---DemoProvider2.php 

寫到這裡你可能問我的工作目錄下三個檔案幹什麼用呢?不要著急,接下來我們逐個建立檔案並進行講解。
1:DemoInterface.php【介面檔案】這個就是laravel中提到的Contracts(契約),使用介面(契約)的原因官方也給了說明:低耦合和簡單性,檔案內容如下:

<?php 
namespace App\Xiaocai\Test;
interface DemoInterface
{ 
    function demo1();
    function demo2(); 
} 

介面中只簡單定義兩個測試方法,記住帶上名稱空間App\Xiaocai\Test,這個很重要;
2:DemoProvider.php【介面實現類】,這個官方並沒有特別說明,當然,有了介面當然會有對應的實現類去實現介面中的方法
檔案內容如下:

<?php 
namespace App\Xiaocai\Test;
class DemoProvider implements DemoInterface
{
    public function demo1()
    {
        return 'demo1';
    }
    public function demo2()
    {
        return 'demo2';
    }
}

對於這個實現類,我是這樣理解的,laravel中的契約(介面)通過規定好方法名稱,這樣,第三方擴充套件包在想要實現這些契約方法的時候,必然要受到契約提供的方法的約束,防止濫用,使使用者在使用laravel基礎上的擴充套件包的時候,不必要再去了解底層程式碼邏輯,方法都是定義好的,儘管不同的包處理的邏輯不同,但是對於使用者來說,都是呼叫的同一個方法,對於如何選擇到底使用哪個實現類,我們也準備好了DemoProvider2.php類,他是DemoInterface.php的第二種實現方法。
3:DemoProvider2.php【介面實現類2】內容如下

<?php 
namespace App\Xiaocai\Test;
class DemoProvider2 implements DemoInterface
{
    public function demo1()
    {
        return 'demo1的第二種實現';
    }
    public function demo2()
    {
        return 'demo2的第二種實現';
    }
}

4.建立測試控制器

命令列執行:

php artisan make:controller TestController

5.新增路由

為測試控制器新增一個測試路由,修改專案/routes/web.php檔案,追加程式碼如下:

Route::get('/test', 'TestController@index');

6.修改服務提供器檔案(TestServiceProvider)

這裡是重點!這裡是重點!這裡是重點!重要的事情我只說三遍

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Xiaocai\Test\DemoInterface;
use App\Xiaocai\Test\DemoProvider;
use App\Xiaocai\Test\DemoProvider2;

class TestServiceProvider extends ServiceProvider
{
    public function boot()
    {
    }
    public function register()
    {
        $this->app->bind(DemoInterface::class, DemoProvider2::class);
    }
}

在這裡就可以對想要使用的實現介面(契約)類進行選擇,$this->app->bind(arg1, arg2);引數1代表介面類,引數2代表要使用的介面實現類,你可以在這裡進行切換選擇實現類,切換之後如何驗證呢?

驗證

修改TestController檔案

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Xiaocai\Test\DemoInterface;//注意引用的是介面檔案,並非實現類

class TestController extends Controller
{
    public function index(DemoInterface $demo)
    {
        dd($demo->demo1());
    }
}

此時瀏覽器輸出介面不出意外的話應該是這樣的:
file
我們不妨修改一下實現類,在TestServiceProvider檔案中修改如下:

$this->app->bind(DemoInterface::class, DemoProvider::class);
//$this->app->bind(DemoInterface::class, DemoProvider2::class);

此時再執行,如下:
file

總結

如此一來,切換實現的方法是不是很簡單,只需要在服務提供器中修改即可,果真是低耦合。如果文章中出現什麼紕漏歡迎指出,防止禍害他人,如果覺得對您有幫助的話,點個贊支援一下吧。

結語

另外Xiaocai工作目錄是測試用的,當然如果做專案的話,你也可以把你的程式碼上傳到composer,這樣通過composer直接引入到vendor目錄下,通過composer的自動載入機制,這樣是不是更能提高你的效率呢。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章