我已经对这个帖子发表了评论,但它似乎已经死了,所以我打开了一个新帖子: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
答案 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对象。
如果有人对此有任何反馈,请发表评论,因为我有兴趣知道。