如何在 Laravel 5.1 中建立服務 Service Provider

2016-10-01    分類:WEB開發、程式設計開發、首頁精華0人評論發表於2016-10-01

本文由碼農網 – 任琦磊原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

這是一份面向初學者的 Laravel 5.1 中構建 Service Provider 的教程。

我在自己過去的部落格中提到了我喜歡 Laravel 5.1 的架構,尤其是它引入了Service Provider,從而使你模組化的構建應用成為了可能。應用的配置常常可能成為棘手的任務,完全取決於你正在使用的框架,但幸運的是,我們正在使用的 Laravel 讓這件事變得相當簡單。

所以讓我們開始建立一個用於演示的路由(route)。到 app/Http/routes.php中新增下面這條路由:

Route::resource('demo', 'DemoController');

通過使用 Route::resource,我們就獲得了預定義好的 index,show,create,edit,update,store 和 destroy 路由。

為了實現良好的對稱性,現在我們可以使用 artisan 命令列工具來為我們建立對應的控制器(controller)。鍵入如下指令:

php artisan make:controller DemoController

讓我們開啟建立好的檔案,將 index 方法修改為如下內容:

public function index()
{
    return view('demo.index');
}

現在讓我們繼續在 app/Resources/views 目錄下建立一個名為 Demo 的資料夾,並在資料夾中建立一個名為 index.blade.php 的檢視(view)檔案,內容如下:

@extends('layouts.master')

@section('content')
<h1>Demo Page</h1>
@endsection

這個例子中我們正在呼叫一個我已經在 layouts 資料夾中建立了的 master 頁面master.blade.php。如果你的 master 用了另一個名字,那麼這裡你得替換掉。如果你沒有 master 頁面,那麼就刪掉第一行 extends 的全部內容,包括 @sectioin 申明。

假設你已經配置好了你的開發環境並解析了你的域名,那麼當你訪問路由yourapplication.com/demo,你應該可以看到內容 Demo Page 了。<wbr>

好的,那麼現在就讓我們來建立一個Service Provider。這個Service Provider不會做太多特別有用的事情。它只是用來向你展示如何搭建它。

讓我們在 app 目錄下建立一個 Helpers 資料夾。然後在 Helpers 資料夾裡,建立一個 Contracts 資料夾。在 Contracts 資料夾裡,建立檔案RocketShipContract.php 並寫入下面的內容:

<?php

namespace App\Helpers\Contracts;

Interface RocketShipContract
{

    public function blastOff();

}

正如你所知,介面(interface)是一種用來強化架構的契約(contract)。為了定義類的介面,它必須包含名為 blastOff 的公共函式(public function)。

所以為什麼要費力地建立一個契約呢?其實,Laravel 有一個神奇的功能是你可以型別提示契約,Service Provider會返回一個受它約束的具體類的例項。這實現了無與倫比的靈活性和鬆耦合的結構,因為你的工作將可以輕鬆地通過一行程式碼來完成。我們即將看到這是如何工作的。

首先,讓我們建立一個具體類。在 app/Helpers 資料夾中,建立RocketShip.php,程式碼如下:

<?php

namespace app\Helpers;

use App\Helpers\Contracts\RocketShipContract;

class RocketShip implements RocketShipContract
{

    public function blastOff()
    {

        return 'Houston, we have ignition';

    }

}

你可以看到我們的具體類沒有做很多事,但我們則對如何配合在一起更感興趣。你可以自己決定你想給你的應用提供什麼服務。

好的,現在我們要來建立一個符合契約和具體類的Service Provider了。在命令列中鍵入下面的指令:

php artisan make:provider RocketShipServiceProvider

回車確認,它就會為你建立好一個類。

新檔案位於 app/Providers。前往這個檔案,修改為如下內容:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Helpers\RocketLauncher;

class RocketShipServiceProvider extends ServiceProvider
{
    protected $defer = true;

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('App\Helpers\Contracts\RocketShipContract', function(){

            return new RocketShip();

        });
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return ['App\Helpers\Contracts\RocketShipContract'];
    }

}

讓我們看一下這一段:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Helpers\RocketShip;

class RocketShipServiceProvider extends ServiceProvider
{

簡單粗暴。我們有了名稱空間,use 申明和 class 申明。當你建立Service Provider時,你要匯入(import)具體類,像這裡我在 use 申明中匯入了 RocketShip。

接下來是:

protected $defer = true;

屬性 $defer 設定為 true 代表這個類只有在必要的時候才會被載入,這樣應用可以更高效地執行。

接下來我們有一個 boot 函式,這只是個空的存根,我們不會對它做任何配置。

然後,我們有 register 方法:

/**
 * Register the application services.
 *
 * @return void
 */
public function register()
{
    $this->app->bind('App\Helpers\Contracts\RocketShipContract', function(){

        return new RocketShip();

    });
}

你可以看到我們正在使用繫結方法來將契約和具體類繫結到一起。這是就是Service Provider定義具體類方法的地方。所以你可以很便捷地調整你想要繫結的類。之後我們會看到這如何起效。

最後,我們有 provides 方法:

/**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return ['App\Helpers\Contracts\RocketShipContract'];
    }

}

如果你把屬性 $defer 設為 true 的話你就會需要這個方法了。

不管怎麼說,這是一個相當簡單的類,只是涵蓋了部分的精華。

好,接下來我們需要告訴我們的應用來找到這個類,我們通過把它新增到config/app.php 中的 providers 陣列來實現。

/*
         * Application Service Providers...
         */

        App\Providers\AppServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
        App\Providers\RocketShipServiceProvider::class,

這裡包含了一些其它的Provider作為參考,你可以看到我們的Provider在最後一行。儲存完你就可以離開這裡繼續後面的了。

我們來修改一下 DemoController 的 index 方法:

public function index(RocketShipContract $rocketship)
{
        $boom = $rocketship->blastOff();

        return view('demo.index', compact('boom'));
}

所以在這裡,我們鍵入 RocketShipContract 並傳遞給例項變數 $rocketship。Laravel 通過Service Provider獲知你其實想要的是 RocketShip 類,因為你在服務提供者裡把它和契約繫結了。是不是很酷?

然後我們簡單地呼叫 blastoff 方法並把它賦值給一個要傳遞向檢視的變數。讓我們來修改一下檢視:

@extends('layouts.master')

@section('content')

    {{ $boom }}

@endsection

你可以看到我正在使用 blade 列印變數。所以瀏覽器中應該可以看到:

Houston, we have ignition.

所以現在為了更簡單的描述能實現什麼,我們可以在 Helpers 資料夾中建立第二個具體類。我們把它命名為 RocketLauncher.php,內容如下:

<?php

namespace app\Helpers;

use App\Helpers\Contracts\RocketShipContract;

class RocketLauncher implements RocketShipContract
{

    public function blastOff()
    {

        return 'Houston, we have launched!';

    }

}

你可以發現這個我們的 RocketShip 類很像,只是 blastoff 方法略有不同。所以我們在Service Provider的 register 方法中修改其中一行程式碼來實現它:

public function register()
    {
        $this->app->bind('App\Helpers\Contracts\RocketShipContract', function(){

            return new RocketLauncher();

        });
    }

還包括 use 申明:

use App\Helpers\RocketLauncher;

根據上面的簡單變動,我們現在有了基於契約約束的不同的實現,所以瀏覽器裡的結果也會產生相應變化。

儘管我們為了這個教程只是做了一個超級無聊的例子,你還是可以通過它看到這個架構的好處。通過編寫一個契約而不是一個具體類,我們給自己提供了一種更靈活和簡單的而方法來管理程式碼。

這裡有一些“陷阱”你需要注意。你沒法直接重新命名一個Service Provider,而是需要刪除它並通過 artisan 新建一個,因為建立時其它地方也會有一些不被注意的改動。這很可能與自動載入(autoload)有關。如果你發生了這類問題,你可以嘗試在命令列執行 composer dump-autoload。如果仍不起作用,那就還是刪除檔案並重新建立吧。

另一件事是務必在最後一步才把Service Provider新增到 config/app.php。如果裡面配置了一個並不存在的類估計 artisan 會崩潰。

Laravel 框架擁有完善的文件,你可以在這裡閱讀更多關於 Laravel Service Provider 的內容。

我希望你能享受這個教程並覺得它有價值。點選頁面來閱讀全部的教程。如果可以,請評論、分享和點贊,謝謝!

我沒有捐款按鈕,但如果你願意支援我的工作或學習更多 Laravel 的知識,你可以通過購買我的書來實現,《Laraboot: laravel 5* For Beginners》,非常感謝。

譯文連結:http://www.codeceo.com/article/laravel-service-provider.html
英文原文:How to Create a Service Provider in Laravel 5.1
翻譯作者:碼農網 – 任琦磊
轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]

相關文章