Dependency injection 如何在symfony3中注入接口(而不是类)?
我对Symfony DependencyInjection组件有问题。我想将接口注入控制器,因此只能使用接口方法。但是,我注意到我可以使用类中实现接口的任何公共方法,这是错误的。我关注这篇伟大的文章: 编写测试服务类和接口Dependency injection 如何在symfony3中注入接口(而不是类)?,dependency-injection,interface,symfony,Dependency Injection,Interface,Symfony,我对Symfony DependencyInjection组件有问题。我想将接口注入控制器,因此只能使用接口方法。但是,我注意到我可以使用类中实现接口的任何公共方法,这是错误的。我关注这篇伟大的文章: 编写测试服务类和接口 interface ITestService { public function interfaceFunction(); } class TestService implements ITestService { public function inter
interface ITestService
{
public function interfaceFunction();
}
class TestService implements ITestService
{
public function interfaceFunction() {/* do somenthing */}
public function classFunction() {/*do somenthing*/}
}
# file: app/config/services.yml
test_service:
class: MyApp\Application\Services\TestService
将我的应用程序服务类配置为服务(测试服务)
将我的控制器配置为服务:
# file: app/config/services.yml
test_controller:
class: MyApp\AppBundle\Controller\TestController
arguments:
- '@test_service'
在控制器中使用服务
class TestController extends Controller
{
private testService;
function _construct(ITestService $testService)
{
$this->testService = $testService;
}
public function indexAction()
{
// This should be inaccesible but it works :(
$this->testService->classFunction();
// This is the only function I should use.
$this->testService->interfaceFunction();
}
这是因为尽管有类型提示,PHP直到运行时才计算要调用的方法。这可能被认为是不可取的,但它允许使用一些技术,例如
这里有一个基于您提供的示例的简化示例(它没有将Symfony容器放入混合中,因为这纯粹与PHP有关)。你可以:
输出:
ServiceWithOtherFunction interfaceFunction
ServiceWithOtherFunction otherFunction
ServiceWithoutOtherFunction interfaceFunction
Fatal error: Uncaught Error: Call to undefined method ServiceWithoutOtherFunction::otherFunction() in /in/mZcRq:28
Stack trace:
#0 /in/mZcRq(43): Controller->indexAction()
#1 {main}
thrown in /in/mZcRq on line 28
Process exited with code 255.
但是当我们注入另一个不包含otherFunction
的实现时,代码在运行时抛出一个错误
:
final class ServiceWithoutOtherFunction implements IService
{
public function interfaceFunction() { echo "ServiceWithoutOtherFunction interfaceFunction\n"; }
}
$controllerWithoutOtherFunction = new Controller(new ServiceWithoutOtherFunction);
$controllerWithoutOtherFunction->indexAction();
输出:
ServiceWithOtherFunction interfaceFunction
ServiceWithOtherFunction otherFunction
ServiceWithoutOtherFunction interfaceFunction
Fatal error: Uncaught Error: Call to undefined method ServiceWithoutOtherFunction::otherFunction() in /in/mZcRq:28
Stack trace:
#0 /in/mZcRq(43): Controller->indexAction()
#1 {main}
thrown in /in/mZcRq on line 28
Process exited with code 255.
如果要使用接口、DI和DIC,则不应调用任何公共方法,而应调用接口公开的方法。这是真正利用接口好处的唯一方法:与实现细节分离,并且能够在不更改
控制器内部任何内容的情况下更改要注入的类
我认为OOP
中不存在这样的概念。你可以试着玩弄trait
s,但既然这些不是可供选择的类型,为什么它不可访问呢$testService
仍然是类testService
的一个对象,该类没有实现一些接口。谢谢,@JovanPerovic和yoshi。嗯,在我的构造函数中,我正在等待一个具有ITestService契约的对象。我应该放弃本合同中不存在的任何方法。我使用c#和castle windsor IoC框架,我只能使用界面中定义的方法。这对我来说是有意义的,但symfony组件让我感到困惑。这是一个PHP问题。只是接口和对象的实现方式。IDE至少应该阻止您使用非接口方法。PHP解析要在运行时调用的方法。您不需要明确的对象类,例如java或C++。事实上,您根本不需要指定类型提示:方法可以很好地工作。类型提示是运行时检查、方法签名的契约。