适配器和依赖注入
我目前正在 PHP 中构建 MVC 应用程序(不使用任何框架)。我正在使用 yadif (https://github.com/beberlei/yadif) 进行依赖注入。
我想构建一个登录模块。它应该能够使用适配器,例如,可以设置使用 MySql 数据库或某个 LDAP 目录对登录进行身份验证。此设置将在管理区域中完成并存储在数据库中。
我想象我会有一个抽象适配器:
<?php
abstract AbstractLoginAdapter{
abstract function login($username, $pass){}
}
然后我会像这样实现适配器:
<?php
MySQLLoginAdapter extends AbstractLoginAdapter{
public function login($username, $pass){
//do stuff
}
}
这一切都很好,但是如何创建适配器的实例?通常,依赖项将通过构造函数使用 yadif 注入:
<?php
class loginController{
private $_adapter;
public function __construct(AbstractLoginAdapter $adapter){
$this->_adapter = $adapter;
}
}
但是,由于我不知道将注入哪个具体适配器,所以我无法事先在配置中设置它。 Yadif 允许我创建一个配置,然后需要将其传递给容器:
$builder = new Yadif_Builder();
$builder->bind("loginController")
->to("loginController")
->args($SelectedLoginAdapter);
由于应用程序使用前端控制器,因此会在其中创建一个 DI 容器。然后它创建一个路由对象等。
鉴于此,我应该将该容器的引用传递给 loginController 对象,然后使用该容器来实例化我的适配器吗?
或者我应该在我的loginController对象中实例化一个新容器,然后加载到适配器的实例中?
I am currently building an MVC application in PHP (not using any frameworks). I am using yadif (https://github.com/beberlei/yadif) for dependency injection.
I would like to build a login module. It should be able to use adapters, for example one might be able to set that logins are authenticated using the MySql database or some LDAP directory. This setting would be done in the admin area and is stored in a database.
I imagine that I would have an abstract adapter:
<?php
abstract AbstractLoginAdapter{
abstract function login($username, $pass){}
}
I would then just implement adapters like so:
<?php
MySQLLoginAdapter extends AbstractLoginAdapter{
public function login($username, $pass){
//do stuff
}
}
That's all nice and well, but how do I create an instance of the adapter? Usually, dependencies would be injected using yadif via the constructor:
<?php
class loginController{
private $_adapter;
public function __construct(AbstractLoginAdapter $adapter){
$this->_adapter = $adapter;
}
}
However, since I don't know which concrete adapter will be injected, I can't set that in a configuration before hand. Yadif allows me to create a configuration which I then need to pass to the container:
$builder = new Yadif_Builder();
$builder->bind("loginController")
->to("loginController")
->args($SelectedLoginAdapter);
Since the application uses a front controller, a DI container is created there. It then creates a routing object etc.
In light of this, should I pass a reference of that container down to the loginController object, and then use that container to instantiate my adapter?
Or should I instantiate a new container within my loginController object and then just load in an instance of the adapter?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我会做第一个:将引用传递给您的控制器。您将希望在应用程序中使用单个依赖项注入器容器 (DIC)。您不想在需要访问新的 DIC 时创建它。这将导致 DIC 中存储的对象重复。
我知道 Symfony 2 就是这样做的。所有控制器(以及许多其他类)都实现 ContainerAware 接口。该接口有一个方法
setContainer()
,用于传递对 DIC 的引用。I would do the first: pass a reference down to your controller. You'll want to use a single Dependency Injector Container (DIC) in your application. You don't want to create a new DIC whenever you need access to it. That would lead to duplication of objects stored in the DIC.
I know this is how Symfony 2 does it. All controllers (and many other classes) implement the
ContainerAware
interface. That interface has a single methodsetContainer()
that is used to pass down a reference to the DIC.我不知道您的具体 DI 工具,但从 DI 角度来看,您将指定要使用的类型。容器本身负责实例化配置类型的新实例(也可能是该类型的所有依赖项)。
在您的示例中,DI 的好处是您可以使用不同的配置部署完全相同的代码,其中一个安装使用 LDAP,另一个安装使用 MySQL 身份验证。
I don't know about your specific DI tool but from a DI point of view you would be specifying which type to use. The container itself is responsible for instantiating a new instance (and possibly of all the dependencies of that type as well) of the configured type.
The benefit of DI in your example would be that you could deploy exactly the same code with a different configuration with 1 installation using LDAP and the other using MySQL authentication.
将类型提示
("AbstractLoginAdapter")
重构为("MySQLLoginAdapter")
。如果你在新的
__CLASS__ // Fatal Error
中调用抽象类方法。Refactor type hinting
("AbstractLoginAdapter")
to("MySQLLoginAdapter")
.If you call abstract class method in the new
__CLASS__ // Fatal Error
.