拥有 PHP DI/IoC 个容器 parameters/arguments
Own PHP DI/IoC Container with parameters/arguments
我正在制作自己的练习框架,但我坚持使用 DI/IoC 容器,在构造函数中发送参数。
Container.php
class Container
{
private $registry = array();
private $shared = array();
public function set($name, Closure $resolve)
{
if (!$this->exists($name)) {
$this->registry[$name] = $resolve;
} else {
throw new Exception('Class with name ' . $name . ' is already registered.');
}
}
public function get($name, $arguments = array())
{
if (!$this->exists($name, 'shared')) {
$this->shared[$name] = $this->getNew($name, $arguments);
}
return $this->shared[$name];
}
public function getNew($name, $arguments = array())
{
if ($this->exists($name, 'registry')) {
$class = $this->registry[$name];
return $class();
}
throw new Exception('Class with name ' . $name . ' does not exist.');
}
private function exists($name, $type = 'registry')
{
return array_key_exists($name, $this->$type);
}
}
用法:
$container = new Container;
$container->set('file', function() {
return new Application\Library\File();
});
$container->set('cache', function($path, $type = 'json') use ($container) {
return new Application\Library\Cache($container->get('file'), $path, $type);
});
$params = array (
'path/to/cache/',
'json'
);
$cache = $container->get('cache', $params);
问题是:如何使用 get() 或 getNew() 方法将 parameters/arguments 发送给构造函数。我看到 ReflectionClass($classname) 和 newInstanceArgs($args) 但我不知道如何使用它以及在哪里使用把它。
编辑 - 可能是这样的:
public function getNew($name, $arguments = array())
{
if ($this->exists($name, 'registry')) {
if (count($arguments) > 0) {
$object = new ReflectionClass($name);
return $object->newInstanceArgs($arguments);
} else {
$class = $this->registry[$name];
return $class();
}
}
throw new Exception('Class with name ' . $name . ' does not exist.');
}
但它不起作用,因为为了创建 Cache class 我只注入了 3 个参数中的 2 个 $container->get() 和 $params 数组。第一个参数固定在 $container->set() 和 File class 中,它不能正确注入实例创建。有什么解决办法吗?
错误:
可捕获的致命错误:传递给 Application\Library\Cache::__construct() 的参数 1 必须是 Application\Library\File 的实例,给定的字符串
可行但我不满意的可能解决方案:
public function getNew($name, $arguments = array())
{
if ($this->exists($name, 'registry')) {
$class = $this->registry[$name];
$count = count($arguments);
switch ($count) {
case 1:
$object = $class($arguments[0]);
break;
case 2:
$object = $class($arguments[0], $arguments[1]);
break;
case 3:
$object = $class($arguments[0], $arguments[1], $arguments[2]);
break;
case 4:
$object = $class($arguments[0], $arguments[1], $arguments[2], $arguments[3]);
break;
default:
$object = $class();
break;
}
return $object;
}
throw new Exception('Class with name ' . $name . ' does not exist.');
}
计算 $arguments 的数量,通过 switch case 和 return 带有注入参数的 $classname 实例。
我正在制作自己的练习框架,但我坚持使用 DI/IoC 容器,在构造函数中发送参数。
Container.php
class Container
{
private $registry = array();
private $shared = array();
public function set($name, Closure $resolve)
{
if (!$this->exists($name)) {
$this->registry[$name] = $resolve;
} else {
throw new Exception('Class with name ' . $name . ' is already registered.');
}
}
public function get($name, $arguments = array())
{
if (!$this->exists($name, 'shared')) {
$this->shared[$name] = $this->getNew($name, $arguments);
}
return $this->shared[$name];
}
public function getNew($name, $arguments = array())
{
if ($this->exists($name, 'registry')) {
$class = $this->registry[$name];
return $class();
}
throw new Exception('Class with name ' . $name . ' does not exist.');
}
private function exists($name, $type = 'registry')
{
return array_key_exists($name, $this->$type);
}
}
用法:
$container = new Container;
$container->set('file', function() {
return new Application\Library\File();
});
$container->set('cache', function($path, $type = 'json') use ($container) {
return new Application\Library\Cache($container->get('file'), $path, $type);
});
$params = array (
'path/to/cache/',
'json'
);
$cache = $container->get('cache', $params);
问题是:如何使用 get() 或 getNew() 方法将 parameters/arguments 发送给构造函数。我看到 ReflectionClass($classname) 和 newInstanceArgs($args) 但我不知道如何使用它以及在哪里使用把它。
编辑 - 可能是这样的:
public function getNew($name, $arguments = array())
{
if ($this->exists($name, 'registry')) {
if (count($arguments) > 0) {
$object = new ReflectionClass($name);
return $object->newInstanceArgs($arguments);
} else {
$class = $this->registry[$name];
return $class();
}
}
throw new Exception('Class with name ' . $name . ' does not exist.');
}
但它不起作用,因为为了创建 Cache class 我只注入了 3 个参数中的 2 个 $container->get() 和 $params 数组。第一个参数固定在 $container->set() 和 File class 中,它不能正确注入实例创建。有什么解决办法吗?
错误: 可捕获的致命错误:传递给 Application\Library\Cache::__construct() 的参数 1 必须是 Application\Library\File 的实例,给定的字符串
可行但我不满意的可能解决方案:
public function getNew($name, $arguments = array())
{
if ($this->exists($name, 'registry')) {
$class = $this->registry[$name];
$count = count($arguments);
switch ($count) {
case 1:
$object = $class($arguments[0]);
break;
case 2:
$object = $class($arguments[0], $arguments[1]);
break;
case 3:
$object = $class($arguments[0], $arguments[1], $arguments[2]);
break;
case 4:
$object = $class($arguments[0], $arguments[1], $arguments[2], $arguments[3]);
break;
default:
$object = $class();
break;
}
return $object;
}
throw new Exception('Class with name ' . $name . ' does not exist.');
}
计算 $arguments 的数量,通过 switch case 和 return 带有注入参数的 $classname 实例。