【问题标题】:Own PHP DI/IoC Container with parameters/arguments自己的带有参数/参数的 PHP DI/IoC 容器
【发布时间】:2015-04-08 10:26:37
【问题描述】:

我正在制作自己的练习框架,但我被 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() 方法将参数/参数发送给构造函数。我看到了 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 类,我只用 $container->get() 和 $params 数组注入了 3 个参数中的 2 个。第一个参数在 $container->set() 中使用 File 类进行了修复,并且在创建实例时无法正确注入。有什么解决办法吗?

错误: 可捕获的致命错误:传递给 Application\Library\Cache::__construct() 的参数 1 必须是 Application\Library\File 的实例,给定字符串

【问题讨论】:

    标签: php dependency-injection inversion-of-control containers ioc-container


    【解决方案1】:

    可行但我不满意的可能解决方案:

    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 并返回带有注入参数的 $classname 实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-28
      • 2017-08-03
      • 2011-04-29
      • 1970-01-01
      • 2018-05-16
      相关资源
      最近更新 更多