Slim框架中的依赖注入——将容器传递到你自己的类中


Dependency Injection in Slim Framework - passing Container into your own classes

我已经评论了这个线程,但它似乎已经死了,所以我打开一个新的:依赖注入苗条框架3

上面的帖子解释了如何将Slims Container传递给您自己编写的类。

然而,OP已经询问是否有可能让Slim依赖注入所有他们的类。

我也有兴趣知道是否有一种方法可以做到这一点,因为如果你必须将容器传递给每个你想要使用它的类,那么它似乎就是DRY。

作为一个例子,如果我想使用Slim的一个函数(比如在我自己的类中重定向),我不能按照文档的规定使用它:

$res->withStatus(302)->withHeader('Location', 'your-new-uri');

因为$res(响应对象)不在我的类的作用域内,除非我注入/传递它。

这个问题是,如果我说100类,我必须传递(或注入)容器100次吗?这看起来真的,真的很乏味。

在像CakePHP这样的框架中,你可以使用'AppController'全局地做这样的事情,即定义一次东西,并使它在你所有的类中可用。Slim不提供这个功能吗?在我看来,如果不能,那将是一个严重的缺陷。


编辑-我从我所做的评论中添加了这一点,试图进一步解释这个问题:

如果你看第一应用教程- http://slimframework.com/docs/tutorial/first-app.html -他们正在添加一个PDO数据库连接到容器。

假设我在子目录中有100个独立的类(示例中有…/classes/directory),并使用spl_autoload_register()自动加载到index.php中。容器在这些类中都不可用。

如果我必须传递100次单独的东西,每次我使用我的一个类,只是为了获得一个PDO连接(这只是一个例子),那么这使得代码非常重复,即不是DRY。

Slim默认自带痘痘。一些开发人员认为(我倾向于同意他们的观点),Pimple不是一个依赖注入容器,而是一个服务定位器,因为它不能自己解析依赖,所以你需要注册它们。

Slim 3可以与任何实现容器互操作接口的依赖管理器一起工作,PHP-DI也可以。

选择这个包。这就是我在我的项目中使用的,因为自动装配,它简直太神奇了。简单地说,PHP-DI读取类的构造函数,并了解需要注入的内容,因此您不必像使用Pimple那样注册依赖项。

有时我认为(希望?)PHP-DI将取代Pimple作为Slim的默认DI容器,因为它只是更高级。

如何处理痘痘:

<?php
namespace Controllers;
class UsersController
{
    // Inject Container in controller (which is bad, actually)
    public function __construct(ContainerInterface $container)
    {
        // grab instance from container
        $this->repository = $container['userRepository'];
    }
    // Handler of a route
    public function getAllUsers($request, $response)
    {
        $user = $this->repository->getAllUsers();
        return $response->withJson($users);
    }
}

下面是PHP-DI的相同控制器:

<?php
namespace Controllers;
class UsersController
{
    // Declare your dependencies in constructor:
    // PHP-DI will find the classes and inject them automatically
    public function __construct(UserRepository $repository)
    {
        $this->repository = $repository;
    }
    // Handler of a route
    public function getAllUsers($request, $response)
    {
        $user = $this->repository->getAllUsers();
        return $response->withJson($users);
    }
}

问题是,如果我有100门课,我必须通过吗(或注射)容器100次?这看起来真的,真的乏味。

如果您将Slim与PHP-DI捆绑使用,那么问题将通过autotowiring自动解决。:)

最简单的方法如下:

index . php

$app->get('/mytest', ''TestController:mytest');

TestController.php

class TestController {
    protected $ci;
    public function __construct(Slim'Container $ci) {
        //var_dump($ci);
        $this->ci = $ci;
    }
    public function mytest() {
        $sql = ''; // e.g. SQL query
        $stmt = $this->ci->db->prepare($sql);
    }
}

我不确定这是否是"正确"的方式,但发生的事情是TestController的构造函数接收容器作为第一个参数。这在他们的文档中有提到:http://www.slimframework.com/docs/objects/router.html#container-resolution

所以当你使用像TestController::mytest()这样的函数时,它可以访问容器中的任何东西,例如你在index.php中设置的PDO数据库实例(如果遵循他们的第一个应用程序示例教程)。

正如我所说,我不确定这是否是"正确"的方法,但它有效。

如果你取消注释var_dump($ci)行,你会看到Slim Container对象。

如果有人对此有任何反馈,请评论,因为我很想知道。