我想知道如何使用php(用于研究)实现依赖注入容器。我得到了依赖注入的概念,我可以实现它,但我只能考虑到php框架的控制器。
意味着整个实例化,注入等都发生在控制器中。像
class SampleController{
public function action1(){
$sample_object = new ObjectToInject();
$dependent_object = new DependentObject($sample_object);
$dependent_object->doSomething();
...
etc
}
}
现在我所说的是如果逻辑变得更复杂,控制器会变得臃肿。我知道我的控制器变得臃肿,这是不是意味着它仍然不那么可维护?
问题:
如果我的问题含糊不清,请纠正我。 感谢
答案 0 :(得分:4)
这是一个非常重要的问题。要快速回答您的观点:
(1)不。这不正确。虽然您必须在某处进行布线,但它不应该在您的控制器中。您的控制器应仅接收完成其工作所需的完全构建的对象。不要给他们超过他们需要的东西。 例如:
class UserController
{
public function __construct(UserRepository $UserRepository)
{
$this->UserRepository = $UserRepository;
}
public function showUser($id)
{
$User = $this->UserRepository->find($id);
}
}
请注意UserController
只有UserRepository
作为依赖项? UserRepository
同时可能看起来像这样:
class UserRepository
{
protected $registry = array();
public function __construct(UserFactory $UserFactory, UserMapper $UserMapper)
{
$this->UserFactory = $UserFactory;
$this->UserMapper = $UserMapper;
}
public function find($id)
{
if (isset($this->registry[$id]) {
return $this->registery[$id];
}
$User = $this->UserMapper>find($id);
$this->registry[$User->id] = $User;
return $User;
}
public function findOrNew($id)
{
if (!$User = $this->UserMapper->find($id)) {
$User = $this->UserFactory->make(array('id' => $id));
}
return $User;
}
}
UserController
UserFactory
如果不直接需要UserMapper
或UserRepository
个对象,则应该不知道它们。此外,您的DataAccessLayer
不应该知道注入UserMapper
的{{1}}。 UserMapper
也不需要知道DataAccessLayer
依赖于PDOConnection
对象而不是其他对象。
(2)容器的使用是做你不应该在控制器中做的事情:连接你所有的依赖关系。了解DI容器及其工作原理的最简单,最简单的方法是下载并使用Pimple。它是一个非常简单,直接的DI容器,它有很好的文档记录:https://github.com/fabpot/Pimple
(3)这是一个很大的话题。 Symfony是Pimple的更高级版本。我建议学习Pimple,然后阅读Symfony的文档并查看他们使用的示例。还可以查看Laravel's,甚至是PHP-DI https://github.com/mnapoli/PHP-DI
(4)和以前一样见疙瘩:https://github.com/fabpot/Pimple
(5)只要有测试内容,您应该努力测试所有代码逻辑。据推测,应用程序中的每个方法/函数/类都 ,因此您应该测试它正在做它应该做的事情。你不必做的是测试它的任何依赖都在做它们应该做的事情,因为你可能正在测试它们。您相信传入一个类或方法的数据已经过测试,然后您只测试新类/方法要执行的操作。
但同样,我强烈建议学习Pimple,然后尝试像PHP-DI这样的东西,看看自动反射和自动解析依赖关系是如何工作的。最好的方法就是让自己沉浸在各种容器中,并与它们一起玩耍。
答案 1 :(得分:1)
实例化依赖关系不是“逻辑”,它只是配置。
AmgLauncher写了一个很好的答案,我想提供一个更简单的答案:控制器与服务无异。您应该在控制器上使用依赖注入,就像服务一样。
问题在于:Symfony不鼓励(至少通过他们的文档)。不要盲目跟随Symfony的DIC文档。
所以最后,问题是:但是如果它有依赖关系,那么构建我的控制器的是什么/谁?
这是容器的工作。容器将构建您的控制器和所有服务。问题是一些框架不能以这种方式工作。在Symfony 2中,有一个选项:Controllers as services。
如果您要使用Pimple,则必须编写创建所有控制器的所有代码。那是无用/无聊的代码。疙瘩不太适合。
正如AgmLauncher建议的那样,还要看PHP-DI,例如this guide about how to write controllers。我还建议您阅读What is a DI container and how it works的简单介绍。 (免责声明:我是PHP-DI的维护者)