9.Laravel5學習筆記:在laravel中註冊自己的服務到容器中
問題描寫敘述
或許標題寫的不夠清楚。實際情況是,在我使用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中註冊自己的服務到容器中