php注册 绑定的容器,(四)从零编写PHP容器-添加绑定解析

功能实现

代码优化

添加绑定解析,优先从绑定实例中获取参数实例

use Closure;

use Exception;

use Psr\Container\ContainerExceptionInterface;

use ReflectionClass;

use ReflectionException;

use ReflectionParameter;

class Container

{

/**

* @var array

*/

protected $binds = [];

/**

* @param string $abstract

* @param mixed $instance

* @return $this

*/

public function bind(string $abstract, $instance)

{

$this->binds[$abstract] = $instance;

return $this;

}

/**

* create a new object

* @param string $abstract

* @return Closure|object

* @throws ReflectionException

* @throws Exception

*/

public function create($abstract)

{

return $this->createInstance($abstract);

}

/**

* create new instance

* @param string $abstract

* @param array $tmp

* @return Closure|object

* @throws ReflectionException

* @throws Exception

*/

protected function createInstance(string $abstract, array $tmp = [])

{

if (isset($this->binds[$abstract])) {

return $this->binds[$abstract];

} else if (isset($tmp[$abstract])) {

return $tmp[$abstract];

} else if (array_key_exists($abstract, $tmp)) {

throw new class('can not create a circular dependencies class object.') extends Exception implements ContainerExceptionInterface{ };

} else {

$tmp[$abstract] = null;

}

$refClass = new ReflectionClass($abstract);

if ($refClass->isInterface() || $refClass->isAbstract()) {

throw new class('can not create a class in interface or abstract.') extends Exception implements ContainerExceptionInterface{ };

} elseif ($refClass->getName() === Closure::class) {

return function () {};

} elseif ($refClass->hasMethod('__construct')) {

$_constructParams = array_map(function (ReflectionParameter $param) use ($abstract, $tmp) {

if ($result = $this->paramsHandle($param) instanceof ReflectionClass) {

return $this->createInstance($param->getClass()->getName(), $tmp);

} else {

return $result;

}

}, $refClass->getMethod('__construct')->getParameters());

}

return $tmp[$abstract] = $refClass->newInstance(... ($_constructParams ?? []));

}

/**

* @param ReflectionParameter $param

* @return mixed|ReflectionClass|null

* @throws ReflectionException

*/

private function paramsHandle(ReflectionParameter $param)

{

if ($param->getClass()) {

return $param->getClass();

} elseif ($param->isDefaultValueAvailable()) {

return $param->getDefaultValue();

} elseif ($param->getType()) {

return [

'string' => '',

'int' => 0,

'array' => [],

'bool' => false,

'float' => 0.0,

'iterable' => [],

'callable' => function() {}

][$param->getType()->getName()] ?? null;

} else {

return null;

}

}

}

注: AbsSingleton为实现单例的抽象类,包含一个getInstance()静态方法,可忽略

实现思路

实现思路

将基础数据类型判断先做分离(方便后期会做基础数据的动态映射)

在容器类中添加一个binds存储绑定的类

在创建方法createInstance中读取变量

示例

class E

{

protected $msg;

public function __construct($msg)

{

$this->msg = $msg;

}

public function show()

{

return $this->msg;

}

}

class D

{

protected $e;

public function __construct(E $e)

{

$this->e = $e;

}

public function show()

{

$this->e->show();

}

}

$container = new Container();

$container->bind(E::class, new E('123'));

# 将获取到绑定的`new E('123')`的实例

$e = $container->create(E::class)

$e->show(); // 123

$d = $container->create(D::class)

$d->show(); // 123

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值