问题描述
也许标题写的不够清楚,实际情况是,在我使用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]
。不胜感激,谢谢!!!
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-25 07:02:35