$this->container 在 Symfony3 上的控制器中为 NULL [英] $this->container is NULL in Controller on Symfony3
问题描述
当我在控制器 (ClientDomainController) 中调用它时遇到了一个烦人的问题:
I got an annoying problem when I call this in a controller (ClientDomainController) :
$this->getDoctrine()->getManager();
我收到此错误:
Call to a member function has() on null
我查看了堆栈跟踪并看到:
I looked the stack trace and see that :
$this->container is null
我的控制器扩展自 Symfony 控制器组件:
My controller extends from the Symfony Controller component :
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
有趣的是,在另一个控制器 (HomeController) 中,我做了完全相同的事情:
The funny thing is that in an other controller (HomeController) I make the exact same things :
- 从控制器扩展(完全相同的类)
- 获取教义
- 获取实体管理器
- 使用管理器
而且这没有任何错误.
HomeController 和 ClientDomainController 之间的唯一区别是第二个是服务.所以我写在services.yml文件中:
The only one difference between the HomeController and the ClientDomainController is that the second one is a service. So I wrote it in the services.yml file :
services:
client_domain:
class: AppBundle\Controller\ClientDomainController
最后,我测试了很多东西,比如为我的控制器创建一个构造函数并将其添加到 services.yml 文件中(从来没有对功能性文件做过的事情):
Finally I tested many things like creating a constructor to my controller and adding this to the services.yml file (things that a never did to the functional one) :
arguments: [ 'doctrine.orm.entity_manager' ]
推荐答案
当您将控制器注册为服务时,Symfony 会按照您的要求创建它.
When you register your controller as a service, then, Symfony creates it just like you tell it to do.
所以不同的是,虽然你的控制器实现了ContainerAwareInterface
(通过扩展Controller
类),但最终没有人调用setContainer
方法来利用这个接口并设置 $container
的值.您必须在 services.yml 配置中手动执行此操作,例如:
So the difference is that although your controller implements ContainerAwareInterface
(via extending Controller
class), in the end nobody calls setContainer
method to utilize this interface and set $container
's value. You have to do it manually in you services.yml config like:
calls:
- [ setContainer, [ @service_container ] ]
但这不是最好的解决方案
将您的控制器注册为服务通常是好的.它使它们更具可测试性和可维护性.
Registering your controllers as services is good in general. It makes them more testable and maintainable.
但只要您遵守面向对象编程的良好规则,这就是事实.在这种情况下,当您传递整个容器时,这意味着:
But this is true as long as you stick to the good rules of OOP. In this case when you pass whole container it means that:
- 如果您不传递容器,您的控制器实例可能具有无效状态(或者您应该处理它可能不会在您使用它的任何地方设置),这在设计上很糟糕.
- 很难测试,因为您必须模拟整个容器,而不仅仅是该控制器使用的依赖项.
- 依赖项没有明确定义,因为您需要查看控制器的代码才能知道从容器中获取的依赖项是什么.
简而言之,依赖应该像你最后那样通过委托人传递,或者你可以使用 基于动作的依赖注入,当一个依赖只在这个特定的动作中使用时.
In short words, dependences should be passed via contrustor as you did in the end or you could use action-based dependency injection when a dependency is used only in this particular action.
实际上最好的解决方案是甚至不扩展基本的 Controller
类以使您的控制器框架独立.
Actually best solution would be even not to extend base Controller
class to make you controllers framework independent.
这篇关于$this->container 在 Symfony3 上的控制器中为 NULL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!