在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 "DECApplicationController" cannot be resolved: Parameter $request of __construct() has no value defined or guessable
Full definition:
Object (
class = DECApplicationController
scope = singleton
lazy = false
__construct(
$service = get(DECFoo)
$request = #UNDEFINED#
)
)
n.b。:如果我输入请求和/或切换构造函数
中的参数顺序,则该错误保持不变。查看错误,我推断Matthew Napoli提出的:: call((解决方案如果我仅使用服务实例化控制器并将请求作为操作方法的参数传递。
。这是否意味着我不能依靠容器进行"部分"注入?
更新2
有关此更新中描述的解决方案,请查看我对问题的回答
不清楚您尝试过什么,但这应该称为操作方法并将其传递为请求(并解决所有依赖关系的控制器(:
$container->call([MyController::class, 'action_name'], [
'request' => $request,
]);
在此处阅读有关call()
的更多信息:http://php-di.org/doc/container.html#call
关于请求:
不要键入$请求参数:
public function __construct($request, /*...*/) {}
或键入它的请求接口:
public function __construct(RequestInterface $request, /*...*/) {}
在这两种情况下,DIC将无法自动创建请求实例。然后您可以自己注入。
关于服务:
用混凝土键入它,例如"服务"。然后,服务实例将由DIC自动创建,其所有依赖项(data_source(。
或使用接口(例如" ServiceInterface"(键入它,并在PHP定义中使用别名在DIC中为其设置一个条目。这样的东西:
return [
'ServiceInterface' => DIget('<NAMESPACE-TO>Service'),
];
请参阅:
php-di"限制" http://php-di.org/doc/autowiring.html#limitations
php-di" php定义 - 别名" http://php-di.org/doc/doc/php-definitions.html#aliases
希望这有所帮助。
我通过在要求控制器之前在容器中设置我的请求来完成此操作:
$container->set('DECRequest', new Request('GET'));
$controller = $container->get('DECApplicationController');
$response = $controller->index();