container在php,PHP的容器Container如何保证唯一?

前提:

我在试着实现一个Psr容器,有get、set、has、make等方法,set就直接保存对象,get就判断存在则调用make,make根据对象是闭包还是实例依此反射函数或类,如果类的构造函数或闭包所需的函数列表里存在类,则继续调用make方法去获得实例。

例子1

class Foobar

{

public function __construct(Container $ci)

{

echo "所需参数是具体的容器对象";

}

}

例子2

class Foobar

{

public function __construct(\Psr\Container\ContainerInterface $ci)

{

echo "所需参数是需实现了Psr容器接口的对象";

}

}

一般容器的调用方式

$contaienr->make(Foobar::class);

// 不考虑下面这个方式

//$contaienr->make(Foobar::class, $container);

问题来了,如何在调用时不将$container实例传过去,却能保证容器对象始终是唯一的呢?

下面是我具体的容器代码,经测试一般的调用没什么问题,只是如果对象需要保证是唯一的单例,我就不知道该如何处理比较好。

declare(strict_types = 1);

namespace Hello;

use ReflectionClass;

use ReflectionFunction;

use ReflectionFunctionAbstract;

use Psr\Container\ContainerInterface;

use Hello\Exception\Exception;

use Hello\Exception\NotFoundException;

class Container implements ContainerInterface

{

/**

* 资源对象

*/

private $resource = [];

/**

* 获取对象

*/

public function get($id)

{

if ($this->has($id)) {

return $this->make($id);

} else {

throw new NotFoundException("{$id} 没有找到!");

}

}

/**

* 设置对象

*/

public function set($id, $object)

{

$this->resource[$id] = $object;

}

/**

* 判断对象是否存在

*/

public function has($id)

{

return array_key_exists($id, $this->resource);

}

/**

* 删除对象

*/

public function remove($id)

{

if ($this->has($id)) {

unset($this->resource[$id]);

} else {

throw new NotFoundException("{$id} 没有找到!");

}

}

/**

* 创造对象

*/

public function make($id, $userParams = [])

{

// 已经存在

if (isset($this->resource[$id])) {

return $this->resource[$id];

}

// 判断对象

if (is_callable($id)) {

// 函数

return $this->call($id, $userParams);

} else if (is_string($id) && class_exists($id)) {

// 类名

return $this->instance($id, $userParams);

} else {

// 其他

return $id;

}

}

/**

* 参数

*/

public function parameters($object, $userParams = [])

{

// 反射函数

$func = $object instanceof ReflectionFunctionAbstract ? $object : new ReflectionFunction($object);

// 参数处理

$userParams = is_array($userParams) ? $userParams : [$userParams];

// 函数名称

$funName = $func->getName();

// 函数所需参数

$funParams = $func->getParameters();

if (empty($funParams)) {

return $userParams;

}

// 循环所需参数

$args = [];

foreach ($funParams as $key => $item) {

$class = $item->getClass();

$name = $item->getName();

if (!empty($class)) {

// 参数是对象,去实例化注入

$args[] = $this->instance($class);

}

}

return array_merge($args, $userParams);

}

/**

* 实例

*/

public function instance($class, $userParams = [])

{

// 反射类

$ins = $class instanceof ReflectionClass ? $class : new ReflectionClass($class);

// 是否可实例化

if (!$ins->isInstantiable()) {

throw new \Exception("{$ins->getName()} 无法实例化!");

}

// 构造函数

$construct = $ins->getConstructor();

// 解析参数

$params = empty($construct) ? [] : $this->parameters($construct, $userParams);

// 返回实例

return $ins->newInstanceArgs($params);

}

/**

* 函数

*/

public function call($func, $params = [])

{

// 获取参数

$params = $this->parameters($func, $params);

return $func(...$params);

}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值