Slim Framework 中的依赖注入 - 将 Container 传递给你自己的 类

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

我已经评论过这个话题,但它似乎已经死了所以我打开一个新的:

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

但是,OP 询问是否有可能让 Slim 进行依赖注入 ALL 他们的 classes.

我也很想知道是否有办法做到这一点,因为如果你必须将容器传递给 every class 你想使用它。

例如,如果我想使用 Slim 的功能之一(例如进行重定向,在我自己的 classes 之一中)我不能使用根据文档:

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

因为$res(响应对象)不在我class的范围内,除非我inject/pass它。

这个问题是,如果我说 100 classes,我是否必须通过(或注入)容器 100 次?这看起来真的非常乏味。

在像 CakePHP 这样的框架中,您可以使用 'AppController' 在全局范围内做这样的事情,即定义一次,并使其在您的所有 class 中可用。 Slim 不提供这个功能吗?如果不是,那是一个严重的缺点,IMO。


编辑 - 我从我发表的评论之一中添加此内容以尝试进一步解释该问题:

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

假设我在子目录中有 100 个单独的 classes(该示例有一个 ../classes/ 目录)并使用 index.php 自动加载它们 spl_autoload_register()。该容器在任何 classes 中都不可用。

如果我必须分别传递某些东西 100 次,每次我使用我的 classes 之一,只是为了获得 PDO 连接(这只是一个例子),那么这会使代码非常重复,即不干燥。

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

Slim 3 可与任何实现 Container interop interface 的依赖管理器一起工作,而 PHP-DI 可以。

争取 this package. This is what I'm using for my projects and it's simply amazing, because of autowiring。简而言之,PHP-DI 读取 class 的构造函数并了解需要注入的内容,儿子,您不必像使用 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);
    }
}

The problem with this is, if I have say 100 classes, do I have to pass (or inject) the container 100 times? That seems really, really tedious.

如果您使用与 PHP-DI 捆绑在一起的 Slim,问题会通过自动装配自动 解决。 :)

最简单的方法如下:

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);
    }
}

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

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

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

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

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