$this->container is NULL in Controller on Symfony3

早过忘川 提交于 2021-01-27 18:47:28

问题


I got an annoying problem when I call this in a controller (ClientDomainController) :

    $this->getDoctrine()->getManager();

I got this error :

    Call to a member function has() on null

I looked the stack trace and see that :

    $this->container is null

My controller extends from the Symfony Controller component :

    use Symfony\Bundle\FrameworkBundle\Controller\Controller;

The funny thing is that in an other controller (HomeController) I make the exact same things :

  1. Extend from Controller (the exact same class)
  2. Get Doctrine
  3. Get the EntityManager
  4. Use the manager

And this without any error.

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

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' ]

回答1:


When you register your controller as a service, then, Symfony creates it just like you tell it to do.

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 ] ]

But this is not the best solution

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:

  1. Your controller instance may have an invalid state if you do not pass container (or you should handle that it may not be set everywhere you use it), which is bad by design.
  2. It's hard to test, since you have to mock whole container instead of only dependences that this controller uses.
  3. Dependences are not explicitly defined as you need to look into controller's code in order to know what are the dependences fetched form container.

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.

Actually best solution would be even not to extend base Controller class to make you controllers framework independent.




回答2:


Your controller should be like this:

class HelperController extends Controller
{

    /**
     * @var \Symfony\Component\DependencyInjection\ContainerInterface
     */
    protected $container;

    /**
     * HelperController constructor.
     *
     * @param ContainerInterface $container
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }
  }

and in config file (in my case xml)

    <service id="xxx.helper_controller" class="xxx\EspacePROBundle\Controller\HelperController">
        <argument type="service" id="service_container" />
    </service>

I hope it help.




回答3:


As stated in Jakub Matczak's answer the DI container for the controller is not set.

Alternatively to adding the calls section in your services.yml you can call setContainer in the constructer of the class where you want to use the controller.

use App\Controller\MyController;
use Symfony\Component\DependencyInjection\ContainerInterface;

class MyClass {

    /**
     * The injected controller
     * @var MyController
     */
    protected $my_controller;

    public function __construct(MyController $my_controller, ContainerInterface $container) {
        $this->my_controller = $my_controller;
        $this->my_controller->setContainer($container);
    }
}


来源:https://stackoverflow.com/questions/46711482/this-container-is-null-in-controller-on-symfony3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!