在MVC上下文中,我有一个依赖于服务的控制器,该服务依赖于data_source(在特定情况下,客户端从第三方API获取数据)。
为了在测试时使用模拟data_source实例化服务,服务的构造函数需要一个data_source。 控制器也是如此,其构造函数需要一个服务。
创建控制器时,我也想传递一个请求对象,因为我更喜欢这个
new Controller(request, service).action_name
到这个
new Controller(service).action_name(request)
在不使用任何容器进行依赖注入的情况下实现此目标是微不足道的。
我不明白如何使用php-di
这样做我的目标是让容器将服务注入控制器,同时自己将请求对象传递给控制器。
更新1
这是我的ApplicationController
namespace DEC;
class ApplicationController {
private $service;
private $request;
public function __construct(Foo $service, $request) {
$this->service= $service;
$this->request = $request;
}
public function index() {
$out = $this->service->foo();
$out .= $this->request->method();
return $out;
}
}
Foo跟随
namespace DEC;
class Foo {
public function __construct() {
}
public function foo() {
return "FOO";
}
}
这是我的要求
namespace DEC;
class Foo {
public function __construct() {
}
public function foo() {
return "FOO";
}
}
这是我尝试让DI工作,因为我喜欢:
$container = ContainerBuilder::buildDevContainer();
$response = $container->call([ApplicationController::class, 'index'], [
'request' => new Request('GET')
]);
echo $response;
这是我得到的错误:
Entry "DEC\ApplicationController" cannot be resolved: Parameter $request of __construct() has no value defined or guessable
Full definition:
Object (
class = DEC\ApplicationController
scope = singleton
lazy = false
__construct(
$service = get(DEC\Foo)
$request = #UNDEFINED#
)
)
N.B。:如果我在构造函数中键入提示请求和/或切换params的顺序,则错误保持不变
查看错误,我推断Matthew Napoli提出的:: call()解决方案是有效的,如果我只用服务实例化控制器并将请求作为action方法的参数传递。
这是否意味着我不能依靠容器来支持"部分"注射?
更新2
对于本次更新中描述的解决方案,请查看我自己对问题的回答
答案 0 :(得分:0)
你所尝试的内容不是很清楚,但这应该调用action方法并将请求传递给它(并解析控制器及其所有依赖项):
$container->call([MyController::class, 'action_name'], [
'request' => $request,
]);
在此处详细了解call()
:http://php-di.org/doc/container.html#call
答案 1 :(得分:0)
关于请求:
请勿键入提示$ request参数:
public function __construct($request, /*...*/) {}
或者为它提示一个RequestInterface:
public function __construct(RequestInterface $request, /*...*/) {}
在这两种情况下,DIC都无法自动创建请求实例。然后你可以自己注射它。
关于服务:
使用混凝土提示类型,例如"服务"。然后,DIC将自动创建一个服务实例及其所有依赖项(data_source)。
或使用接口键入提示,例如" ServiceInterface",并使用PHP定义中的别名在DIC中为其设置条目。像这样:
return [
'ServiceInterface' => DI\get('<NAMESPACE-TO>\Service'),
];
请参阅:
PHP-DI&#34;限制&#34;在http://php-di.org/doc/autowiring.html#limitations
PHP-DI&#34; PHP定义 - 别名&#34;在http://php-di.org/doc/php-definitions.html#aliases
希望这会有所帮助。
答案 2 :(得分:0)
我设法通过在请求控制器之前在容器中设置我的请求来完成此操作:
$container->set('DEC\Request', new Request('GET'));
$controller = $container->get('DEC\ApplicationController');
$response = $controller->index();