如何在symfony3中注入接口(而不是类)?

时间:2016-12-05 09:39:35

标签: dependency-injection interface symfony

我遇到Symfony DependencyInjection组件的问题。我想将接口注入控制器,所以我只能使用接口方法。但是,我注意到我可以使用实现接口的类中的任何公共方法,这是错误的。我按照好文章:http://php-and-symfony.matthiasnoback.nl/2014/05/inject-a-repository-instead-of-an-entity-manager/

编写测试服务类和接口

interface ITestService
{
    public function interfaceFunction();
}

class TestService implements ITestService
{
    public function interfaceFunction() {/* do somenthing */}

    public function classFunction() {/*do somenthing*/}
}

将我的应用程序服务类配置为服务(test_service)

# 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();
    }

1 个答案:

答案 0 :(得分:3)

作为@Timurib says,这是因为尽管有类型提示,但PHP不会评估要在运行时调用的方法。这可能被视为不合需要的东西,但它允许使用一些技术,如Duck Typing

这里有一个基于您提供的简化示例(它没有将Symfony Container放入混合中,因为这与PHP完全相关)。你可以run it on 3v4l.org

ServiceWithOtherFunction interfaceFunction
ServiceWithOtherFunction otherFunction

输出:

otherFunction

但是当我们注入另一个不包含Error的实现时,代码会在运行时抛出final class ServiceWithoutOtherFunction implements IService { public function interfaceFunction() { echo "ServiceWithoutOtherFunction interfaceFunction\n"; } } $controllerWithoutOtherFunction = new Controller(new ServiceWithoutOtherFunction); $controllerWithoutOtherFunction->indexAction();

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.

输出:

Controller

如果您正在使用接口,DI和DIC,则不应该调用任何公共方法而不是接口公开的方法。这是真正利用接口优势的唯一方法:与实现细节分离,并且能够在不更改deleteInstanceId()内的任何内容的情况下更改要注入的类。