Php Slim Framework 3-如何将$logger注入路由控制器
我使用的是slimframework3。我想将Php Slim Framework 3-如何将$logger注入路由控制器,php,dependency-injection,slim,slim-3,Php,Dependency Injection,Slim,Slim 3,我使用的是slimframework3。我想将dependencies.php中定义的$logger注入路由器控制器类。下面是我做的,有没有更好的办法 routes.php $app->get('/test', function($request, $response, $args){ $controller = new AccountController($this->get('logger')); return $controller->test($request,
dependencies.php
中定义的$logger
注入路由器控制器类。下面是我做的,有没有更好的办法
routes.php
$app->get('/test', function($request, $response, $args){
$controller = new AccountController($this->get('logger'));
return $controller->test($request, $response, $args);
});
AccountController
class AccountController{
private $logger;
function __construct($logger){
$this->logger = $logger;
}
public function test($request, $response, $args){
$this->logger->info('i am inside controller');
return $response->withHeader('Content-Type', 'application/json')->write('test');
}
}
class AccountController
{
protected $ci;
//Constructor
public function __construct(ContainerInterface $ci)
{
$this->ci = $ci;
}
public function test($request, $response, $args)
{
$this->ci->get('logger')->info('i am inside controller');
return $response->withHeader('Content-Type', 'application/json')->write('test');
}
}
在Slim Framework 3文档中,使用路由控制器的正确方法应为:
$app->get('/test', 'AccountController:test');
但是,当我选择以这种更“优雅”的方式对路线控制器进行编码时,如何将$logger
注入AccountController?根据,您应该能够通过控制器内的容器访问记录器:
AccountController
class AccountController{
private $logger;
function __construct($logger){
$this->logger = $logger;
}
public function test($request, $response, $args){
$this->logger->info('i am inside controller');
return $response->withHeader('Content-Type', 'application/json')->write('test');
}
}
class AccountController
{
protected $ci;
//Constructor
public function __construct(ContainerInterface $ci)
{
$this->ci = $ci;
}
public function test($request, $response, $args)
{
$this->ci->get('logger')->info('i am inside controller');
return $response->withHeader('Content-Type', 'application/json')->write('test');
}
}
当您调用$app->get('/test',AccountController:test')代码>,Slim应自动将容器传递到AccountController
的构造函数中
话虽如此,这与其说是伟大设计的一个例子,不如说是一个方便的特性。正如Rob Allen在他的回答中解释的那样,通过将控制器注入应用程序容器,而不是将容器注入每个控制器,您可以实现更好的模块化,从而更容易测试代码(如果您使用的是单元测试)
看看他的。例如,如果您看一下,您可以看到控制器类如何不再依赖于提供所有服务的神奇容器。相反,您可以在构造函数中显式声明每个控制器需要哪些服务。这意味着您可以更轻松地模拟测试场景中的各个依赖项。为了使控制器更易于测试,您应该通过构造函数将记录器注入控制器
AccountController如下所示:
class AccountController
{
protected $logger;
public function __construct($logger) {
$this->logger = $logger;
}
public function test($request, $response, $args){
$this->logger->info('i am inside controller');
return $response->withJson(['foo' => 'bar']);
}
}
在index.php中设置如下:
$container = $app->getContainer();
$container[Logger::class] = function ($c) {
$logger = new \Monolog\Logger('logger');
return $logger;
};
$container[AccountController::class] = function ($c) {
$logger = $c->get(Logger::class);
return new AccountController($logger);
};
$app->get('/test', 'AccountController:test');
请注意,如果将format route callable设置为字符串“class name”colon“method name”
,则Slim 3将在从DI容器提取控制器类后为您调用该方法。如果类名不是容器的注册密钥,那么它将实例化它并将容器传递给构造函数。谢谢!我怎么会错过那条信息!我通过:function\uuu构造(Slim\container$ci)获得容器这不是将记录器注入控制器的正确方法。因为在本例中,您将注入容器本身。这不是正确的方法。我想你可以看看罗布的答案@是的,我在剩下的回答中提到了。嘿,谢谢你的回答。如果我有10个需要使用记录器的控制器,会发生什么?我创建了10个工厂,因为这些控制器通常具有其他依赖项,例如服务类或数据库映射器。