【发布时间】:2017-04-28 15:43:33
【问题描述】:
在 MVC 上下文中,我有一个依赖于服务的控制器,该服务又依赖于 data_source(在特定情况下,客户端从第三方 API 获取数据)。
为了在测试时使用模拟数据源实例化服务,服务的构造函数需要一个数据源。 控制器也是如此,它的构造函数需要一个服务。
在创建控制器时,我也想向它传递一个请求对象,因为我更喜欢这个
new Controller(request, service).action_name
到这里
new Controller(service).action_name(request)
在不使用任何容器进行依赖注入的情况下实现这一点是微不足道的。
我不明白如何使用php-di
我的目标是通过容器将服务注入控制器,同时自己将请求对象传递给控制器。
更新 1
这是我的应用控制器
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#
)
)
注意:如果我键入提示请求和/或在构造函数中切换参数顺序,则错误保持不变
查看错误,我推断 Matthew Napoli 提出的 ::call() 解决方案在我仅使用服务实例化控制器并将请求作为操作方法的参数传递时有效。
这是否意味着我不能依赖容器进行“部分”注入?
更新 2
对于本次更新中描述的解决方案,请看我自己对问题的回答
【问题讨论】:
-
有什么理由要使用 php-di?它确实使用反射(慢)。您只需将一些第 3 方“黑魔法”添加到您的项目中。您实际上要节省多少打字?只是我的恕我直言。
-
@E_p 没有性能损失,一切都被缓存了。如果你不喜欢反射,你也可以禁用它:php-di.org/doc/autowiring.html#configuration
-
我的代码库很小,我预计不会出现可衡量的性能问题。我选择了 php-di,因为它在 GitHub 上拥有近 1000 名订阅者并且正在积极维护
标签: php dependency-injection php-di