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

时间:2016-10-21 11:53:29

标签: php slim

我已经对这个帖子发表了评论,但它似乎已经死了,所以我打开了一个新帖子:Dependency Injection Slim Framework 3

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

然而,OP已经询问是否可以将Slim转换为依赖注入 ALL 他们的类。

我也有兴趣知道是否有这样做的方法,因为如果你必须将容器传递到你想要的每个类,它似乎只是DRY使用它。

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

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

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

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

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

编辑 - 我在其中一条评论中添加了此内容,以便进一步解释此问题:

如果查看First Application Tutorial - http://slimframework.com/docs/tutorial/first-app.html - 他们正在向容器添加PDO数据库连接。

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

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

2 个答案:

答案 0 :(得分:10)

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

Slim 3适用于任何实现Container interop interface的依赖管理器,PHP-DI可以这样做。

转到this package。这是我用于我的项目的原因,因为autowiring,它简直令人惊叹。简单地说,PHP-DI读取类的构造函数并理解需要注入的内容,不必像在Pimple中那样注册依赖项。

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

以下是对Pimple的处理方法:

<?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次?这看起来真的非常   乏味的。

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

答案 1 :(得分:3)

最简单的方法是:

<强>的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数据库实例(如果遵循他们的第一个应用程序示例教程)。 / p>

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

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

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