问题
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 :
- Extend from Controller (the exact same class)
- Get Doctrine
- Get the EntityManager
- 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:
- 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.
- It's hard to test, since you have to mock whole container instead of only dependences that this controller uses.
- 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