我遇到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();
}
答案 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()
内的任何内容的情况下更改要注入的类。