DI对象方法
DI object method
如何在某些对象方法而不是构造函数中注入依赖项?
下面的示例适用于 __constructor 注入
如何在 indexAction 中注入 DateTime 对象?
app.php
$app['index.controller'] = $app->share(function() use ($app) {
return new Controllers\IndexController(new \DateTime());
});
IndexController.php
namespace Moo\Controllers;
class IndexController
{
private $date;
public function __construct(\DateTime $date)
{
$this->date = $date;
}
public function indexAction()
{
return $this->date->format('y-m-d');
}
}
如果您的 class 根据调用的方法有不同的依赖关系,那么这些方法可能应该在单独的 class 中定义。
如果是控制器,我认为规则很简单。您的操作方法所需的依赖项应通过构造函数传递。请求附带的任何内容都应作为方法参数。
我不确定您要注入哪种依赖项。 如果它们只是服务,那么您应该将控制器拆分为多个 classes。 大量的构造函数参数是一种代码味道。你关心它很好,但你试图以错误的方式解决它。
如果请求随附依赖项,则应将其注入到控制器方法(操作)中。 控制器方法应接受请求并return响应。
所有路由占位符都自动注册为请求属性。因此,如果您的日期来自请求:
$app->get('/my/path/{date}', 'index.controller:indexAction');
它将作为请求属性提供:
public function indexAction(Request $request)
{
$request->attributes->get('date');
}
任何请求属性都可以直接注入控制器:
public function indexAction($date)
{
}
这也意味着,如果您手动设置请求属性,则可以将其注入到您的控制器中。它按名称匹配:
// somewhere in your code (event perhaps)
$request->attributes->set('myDate', new \DateTime());
// in your controller
public function indexAction(\DateTime $myDate)
{
}
最后,您可以将请求附带的简单类型转换为更复杂的类型 route variable converters。
$callback = function ($post, Request $request) {
return new Post($request->attributes->get('slug'));
};
$app->get('/blog/{id}/{slug}', 'your.controller:indexAction')
->convert('post', $callback);
阅读文档了解更多信息。
仅作记录,因为您可能不想这样做,确实可以通过使用扩展方法:
<?php
$app['some_service'] = $app->share(function() use ($app) {
return SomeClass($app['some_dependency']);
});
$app['some_service'] = $app->extend('some_service', function($instance, $app) {
$instance->setSomeDependency($app['another_dependency']);
return $instance;
});
话虽如此,您应该考虑@JakubZalas 的解释,因为您不想在 extend 方法中调用您的控制器操作(您希望由调度员)。
如何在某些对象方法而不是构造函数中注入依赖项?
下面的示例适用于 __constructor 注入
如何在 indexAction 中注入 DateTime 对象?
app.php
$app['index.controller'] = $app->share(function() use ($app) {
return new Controllers\IndexController(new \DateTime());
});
IndexController.php
namespace Moo\Controllers;
class IndexController
{
private $date;
public function __construct(\DateTime $date)
{
$this->date = $date;
}
public function indexAction()
{
return $this->date->format('y-m-d');
}
}
如果您的 class 根据调用的方法有不同的依赖关系,那么这些方法可能应该在单独的 class 中定义。
如果是控制器,我认为规则很简单。您的操作方法所需的依赖项应通过构造函数传递。请求附带的任何内容都应作为方法参数。
我不确定您要注入哪种依赖项。 如果它们只是服务,那么您应该将控制器拆分为多个 classes。 大量的构造函数参数是一种代码味道。你关心它很好,但你试图以错误的方式解决它。
如果请求随附依赖项,则应将其注入到控制器方法(操作)中。 控制器方法应接受请求并return响应。
所有路由占位符都自动注册为请求属性。因此,如果您的日期来自请求:
$app->get('/my/path/{date}', 'index.controller:indexAction');
它将作为请求属性提供:
public function indexAction(Request $request)
{
$request->attributes->get('date');
}
任何请求属性都可以直接注入控制器:
public function indexAction($date)
{
}
这也意味着,如果您手动设置请求属性,则可以将其注入到您的控制器中。它按名称匹配:
// somewhere in your code (event perhaps)
$request->attributes->set('myDate', new \DateTime());
// in your controller
public function indexAction(\DateTime $myDate)
{
}
最后,您可以将请求附带的简单类型转换为更复杂的类型 route variable converters。
$callback = function ($post, Request $request) {
return new Post($request->attributes->get('slug'));
};
$app->get('/blog/{id}/{slug}', 'your.controller:indexAction')
->convert('post', $callback);
阅读文档了解更多信息。
仅作记录,因为您可能不想这样做,确实可以通过使用扩展方法:
<?php
$app['some_service'] = $app->share(function() use ($app) {
return SomeClass($app['some_dependency']);
});
$app['some_service'] = $app->extend('some_service', function($instance, $app) {
$instance->setSomeDependency($app['another_dependency']);
return $instance;
});
话虽如此,您应该考虑@JakubZalas 的解释,因为您不想在 extend 方法中调用您的控制器操作(您希望由调度员)。