如何实现依赖注入容器和依赖注入

KiX*_*lan 2 php design-patterns dependency-injection

我想知道如何使用 php 实现依赖注入容器(供研究)。我得到了依赖注入的概念,我可以实现它,但我只能分解到 php 框架的控制器。

这意味着整个实例化、注入等都发生在控制器中。喜欢

       class SampleController{

       public function action1(){
            $sample_object = new ObjectToInject();
            $dependent_object = new DependentObject($sample_object);
            $dependent_object->doSomething();
            ...
            etc
       }


      }
Run Code Online (Sandbox Code Playgroud)

现在我要说的是,如果逻辑变得更加复杂,控制器就会变得臃肿。我知道我的控制器变得臃肿,这是否意味着它仍然不太可维护?

问题:

  1. 我的假设是否正确,即控制器现在拥有所有逻辑?
  2. 那么依赖注入容器有什么用呢?这和他在这篇文章中作为 bootstrapper 所说的一样吗?
  3. 请解释一下 Symfony2 依赖注入容器的作用。
  4. 请给我一个使用 php 依赖注入容器的具体例子。
  5. 我是否正确,在单元测试中,只需要测试依赖类,而不需要测试独立类。

如果我的问题含糊不清,请纠正我。谢谢

Agm*_*her 5

这是一个非常有负担的问题。快速回答您的观点:

(1)不,这是不正确的。虽然您必须在某处进行接线,但它不应该在控制器中。您的控制器应该只接收完成其工作所需的完整构建的对象。不要给他们超过他们需要的东西。例子:

例子

class UserController 
{
    public function __construct(UserRepository $UserRepository)
    {
        $this->UserRepository = $UserRepository;
    }

    public function showUser($id)
    {
        $User = $this->UserRepository->find($id);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,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;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果不直接需要它们,您UserController应该不了解这些UserFactory对象。UserMapper此外,您UserRepository不应该知道DataAccessLayer被注入的UserMapper. UserMapper也不需要知道是DataAccessLayer依赖于一个PDOConnection对象而不是其他东西。

(2)使用容器是为了做你不应该在控制器中做的事情:连接所有依赖项。了解 DI 容器是什么及其工作原理的最简单方法是下载并使用 Pimple。这是一个非常简单、直接的 DI 容器,并且有详细的文档记录: https: //github.com/fabpot/Pimple

(3)这是一个很大的话题。Symfony 是 Pimple 的更高级版本。我建议学习 Pimple,然后阅读 Symfony 的文档并查看他们使用的示例。另请查看 Laravel,甚至 PHP-DI https://github.com/mnapoli/PHP-DI

(4)如前所述查看Pimple: https: //github.com/fabpot/Pimple

(5)只要有需要测试的东西,你就应该努力测试所有的代码逻辑。据推测,应用程序中的每个方法/函数/类都会执行某些操作,因此您应该测试它是否正在执行其应该执行的操作。您不必做的是测试它的任何依赖项是否正在执行它们应该执行的操作,因为您可能正在测试这些依赖项。您相信传递到一个类或方法的数据已经过测试,然后您仅测试新类/方法的用途。

但我再次强烈建议学习 Pimple,然后尝试 PHP-DI 之类的东西,看看自动反射和自动解析依赖关系是如何工作的。最好的方法就是让自己沉浸在各种容器中并尝试它们。