Php 如何实现DI容器?
我一直在问,在控制器中创建模型层的实例是否错误,即使它隐藏在这样的工厂后面:Php 如何实现DI容器?,php,oop,design-patterns,service,containers,Php,Oop,Design Patterns,Service,Containers,我一直在问,在控制器中创建模型层的实例是否错误,即使它隐藏在这样的工厂后面: parent::getServiceFactory()->create('Car'); 我被告知使用依赖项注入容器来初始化控制器。我整晚都在谷歌上搜索,昨晚,我了解到依赖注入容器(DiC)用于创建对象的实例,并将所需的对象注入其中,而无需在路由器中手动操作-也许我只是误解了这个概念 我读过这篇文章,它显示了以下代码行: $ioc->register('database', new DatabaseServ
parent::getServiceFactory()->create('Car');
我被告知使用依赖项注入容器来初始化控制器。我整晚都在谷歌上搜索,昨晚,我了解到依赖注入容器(DiC)用于创建对象的实例,并将所需的对象注入其中,而无需在路由器中手动操作-也许我只是误解了这个概念
我读过这篇文章,它显示了以下代码行:
$ioc->register('database', new DatabaseServiceProvider($host, $user, $pass))
现在,我假设$host,$user,$pass
只是字符串变量,现在如果我想将对象传递给控制器,我如何动态地知道它需要注入哪些对象
添加这样的类型数组是否正确
$container->register('SomeController', array('Namespace\to\Model1', 'Namespace\to\Model2'));
然后,容器寄存器将创建一个SomeController
的对象,该对象将具有Model1、Model2对象
这样做不对吗?在这种情况下,使用DI
的正确方法是什么?域对象和数据映射器是否也是模型层的一部分
或者在应用程序加载时初始化容器中的所有控制器对象是否正确,这样我就可以轻松使用任何控制器了
我被告知使用依赖项注入容器进行初始化
我的控制器。我整晚都在谷歌上搜索,昨晚,我
了解依赖注入容器(DiC)用于创建
对象的实例,并将所需的对象注入其中
这是正确的
我已经读过这篇文章如何构建PHP依赖项注入
容器
停在那里。这个答案并没有说明如何构建一个容器,而是说明了如何构建一个容器。两者之间有着巨大的区别:
- 服务定位器类似于键/值存储:您将命名的东西放入其中,然后按名称请求它们,定位器将它们返回给您
- 注射容器就像一个工厂:你要求它生产一些东西,它为你生产。产品如何创建的细节可以是完全不透明的,也可以是完全可指定的
class Perishable
{
public function __construct(DateTime $expirationDate) { ... }
}
$locator->set('milk', new Perishable(new DateTime());
$milk = $locator->get('milk');
但是,与注射容器相比,它不能做到这一点:
$milk = $container->build(Perishable::class); // ::class is a PHP 5.5 feature
注入容器能够自行确定易腐
对日期时间
有依赖关系,并解决该依赖关系。这是递归发生的,需要理解的是,所有“叶”依赖项都可以实例化。在这种情况下,DateTime
很容易实例化,因为它是一个具体的类,具有可以无参数运行的构造函数;在其他情况下,如果容器遇到无法直接实例化的依赖项(例如,迭代器
),您必须通过告诉容器该怎么做来提供帮助
现在,我假设$host
,$user
,$pass
只是字符串变量,如果我
要将对象传递给控制器,如何动态地知道
它需要注入的对象
我们现在已经谈到了实现部分:您如何知道易腐
需要日期时间
,以及如何创建该日期时间
您可以使用以下方法进行此操作:
这是一个简单的代码,可以实例化上面给出的易腐的
,但在更一般的情况下,它当然会失败得很厉害(需要正确处理的还有很多,例如递归解析构造函数参数)
添加这样的类型数组正确吗
否,因为您必须违反DRY:将指定SomeController
的依赖项作为其构造函数定义的一部分,并将其注册到容器或定位器中
或者当
应用程序加载,那么我可以轻松使用任何控制器吗
这一点都不正确,正如上面所解释的,您使用的是“容器”这个词,而实际上您在脑海中看到了一个服务定位器。一般来说,服务定位器有许多注入容器没有的缺点。在这种情况下,您应该使用合适的容器。在尝试实际使用DI容器之前,您应该首先了解DI容器是什么以及为什么要使用它。
$class = new ReflectionClass('Perishable');
$constructor = $class->getConstructor();
$arguments = [];
foreach ($constructor->getParameters() as $parameter) {
$argumentClass = $parameter->getClass();
$arguments[] = $argumentClass->newInstance();
}
$result = $class->newInstanceArgs($arguments);