1. 程式人生 > >9.Laravel5學習筆記:在laravel中註冊自己的服務到容器中

9.Laravel5學習筆記:在laravel中註冊自己的服務到容器中

pri script -128 ring nts date require 一次 name

問題描寫敘述


或許標題寫的不夠清楚。實際情況是,在我使用laravel的過程中。須要將自己的一個類,通過服務提供者註冊到IOC容器中,可是在實際操作過程中。出現了下面錯誤:

Unresolvable dependency resolving [Parameter #0 [ <required> $name ]]

意思就是說。我的註冊東西,不能夠進行類型轉換。

我的代碼中沒有進行代碼說明須要的類型。

代碼情況


代碼主要實現的一個功能是,對傳入的字符串進行AES加密。

本來Laravel自身是提供了的,可是因為我須要與Android、IOS進行三個平臺的統一。因此僅僅能自己又一次提供一個能夠在三個平臺間相互轉化的AES加密。

代碼大體結構是,一個 interface

<?

php namespace App\Libary\Contracts\Encryption; use Illuminate\Contracts\Encryption\Encrypter; /** * * * @desc 擴展接口。添加了設置key的接口 * @date 2015年7月15日 */ interface EncrypterInterface extends Encrypter { /** * * 設置加密、解密的key * @param string $key */

public function setKey($key); }

這個接口是繼承自Laravel的核心接口。

僅僅是擴展了一個方法

一個實現類 :

<?php

namespace App\Libary\Encryption;

use App\Libary\Contracts\Encryption\EncrypterInterface;
use RuntimeException;
/**
 * 
 * @desc 使用AES進行加解密
 * @date 2015年7月15日
 */
class AesCrypt implements EncrypterInterface
{
    protected
$hex_iv = ‘xxxxxxx‘; protected $key; public function __construct($key) { // } public function encrypt($str) { // } public function decrypt($payload) { // } public function setKey($key) { // } }

這個類實現了上面的接口,然後要提供一個服務提供者。將這個服務註冊到IOC中去。
服務提供者代碼:

<?php

namespace App\Libary\Encryption;

use Illuminate\Support\ServiceProvider;
use App\Libary\Encryption\AesCrypt;


class AesServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(‘App\Libary\Contracts\Encryption\EncrypterInterface‘, function($app){
            $config = $app->make(‘config‘)->get(‘app‘);

            $key = $config[‘key‘];

            return new AesCrypt($key);
        });
    }
}

然後在一個控制器中調用,假設。控制器名稱叫做 : TestController。代碼例如以下:

public function aes(AesCrypt $aes)
{
    $payload = $aes->encrypt(‘hello world!‘);

    echo $payload , ‘<br />‘;
    echo $aes->decrypt($payload);
}

假設此時執行。這會觸發 BindingResolutionException 這個異常。報錯例如以下:

Unresolvable dependency resolving [Parameter #0 [ <required> $key ]] in class App\Libary\Encryption\AesCrypt

提示說,我這個必須的參數$key。在進行容器綁定的時候。不知道該傳入一個什麽類型。

那麽要解決問題。就須要告訴IOC容器,你須要給我綁定一個什麽依賴的類型進來就OK了。

我這裏明顯須要的是一個字符串。所以能夠通過下面兩種方案解決

方案一:更改 AesCrypt 類的構造函數

這個錯誤因為是未限制構造函數須要的類型,因此,能夠直接先明白它的類型。可做例如以下更改

// 請註意,這裏默認給它的構造函數設置了一個空字符串,那麽在進行綁定時,就能夠檢查到這裏須要傳入一個字符串
public function __construct($key=‘‘)
{
    //
}

方案二:使用接口進行調用 (推薦方法)

在進行測試的時候。我直接使用了實現類。事實上這是不好的,寫接口的目的,本來就是為了減少依賴,減小耦合。所以有接口。幹嘛不用接口呢?

這裏須要改的地方是在控制器中。

// 請註意,這裏傳入的參數限制類型已經變換為接口了
public function aes(EncrypterInterface $aes)
{
    $payload = $aes->encrypt(‘hello world‘);

    echo $payload , ‘<br />‘;
    echo $aes->decrypt($payload);
}

思考


盡管問題得到了解決。可是我的疑惑並未全然消除。在我使用過程中,laravel自身的加密函數 Illuminate\Encryption\Encrypter 它的構造函數並未指定其類型。它構造函數例如以下:

// 並未對$key進行賦空字符串
public function __construct($key, $cipher = ‘AES-128-CBC‘)
{
    //
}

再使用中。也不一定非要使用接口才幹夠。

全然能夠直接使用這個類,也不會剛剛上面的綁定類型的錯誤。

翻看了源代碼,也未找到問題所在。因為如今項目時間比較緊,也僅僅能臨時使用 方案二 來解決我遇到的問題了。

假設有同學遇到過這個問題、有更好的解決方式,歡迎留言或email [email protected]

不勝感激,謝謝。!


Laravel5專題文件夾

9.Laravel5學習筆記:在laravel中註冊自己的服務到容器中