Symfony3.4自定义控制器调用getDoctrine()报has() on null错误如何解决?
问题根因
错误由两个核心原因触发:
- Symfony 控制器的容器注入逻辑晚于构造函数执行,你在
__construct中调用依赖容器的getDoctrine()方法时,容器还未完成注入,处于null状态,因此调用has()方法时报错。 - 你虽然在
service.yml中声明了注入EntityManager,但未在构造函数中接收该参数,依然调用依赖容器的getDoctrine(),服务注册配置完全没有生效。
修复方案
方案一:使用构造函数注入EntityManager(推荐)
直接利用你已经配置的服务注入逻辑,修改CustomController代码接收构造函数参数,无需再调用依赖容器的getDoctrine():
<?php namespace AppBundle\Controller; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class CustomController extends Controller { public $data = []; protected $em; public function __construct(EntityManagerInterface $em) { $this->em = $em; $countAttente = $this->em->getRepository('AppBundle:Commandes')->tailleEnAttente("En attente"); $this->data['countAttente'] = $countAttente; } }
你原来的service.yml配置可以简化为:
AppBundle\Controller\CustomController: arguments: ["@doctrine.orm.entity_manager"]
注意:所有继承CustomController的子控制器如果有自定义构造函数,需要调用parent::__construct($em),同时子控制器也需要注册为服务,传递EntityManager参数。
方案二:将逻辑移到setContainer方法中
如果不想修改所有子控制器的服务配置,可以重写父类的setContainer方法,等容器注入完成后再执行查询逻辑:
<?php namespace AppBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\DependencyInjection\ContainerInterface; class CustomController extends Controller { public $data = []; protected $em; public function setContainer(ContainerInterface $container = null) { parent::setContainer($container); // 此时容器已注入完成,可正常调用getDoctrine() $this->em = $this->getDoctrine()->getManager(); $countAttente = $this->em->getRepository('AppBundle:Commandes')->tailleEnAttente("En attente"); $this->data['countAttente'] = $countAttente; } }
该方案不需要修改service.yml配置,也不需要调整子控制器的代码,适配性更强。
方案三:用Twig全局变量实现(菜单通知类需求最优解)
如果你的统计值只需要在模板中展示,完全不需要耦合到控制器父类,直接配置Twig全局变量更简洁:
- 创建独立服务处理统计逻辑:
// src/AppBundle/Service/OrderCounter.php namespace AppBundle\Service; use Doctrine\ORM\EntityManagerInterface; class OrderCounter { protected $em; public function __construct(EntityManagerInterface $em) { $this->em = $em; } public function getPendingCount() { return $this->em->getRepository('AppBundle:Commandes')->tailleEnAttente("En attente"); } }
- 在
service.yml中注册服务并配置为Twig全局变量:
services: AppBundle\Service\OrderCounter: arguments: ["@doctrine.orm.entity_manager"] twig: globals: order_counter: '@AppBundle\Service\OrderCounter'
- 所有Twig模板中都可以直接调用
{{ order_counter.pendingCount }}获取统计值,不需要修改控制器逻辑。
内容的提问来源于stack exchange,提问作者Silkosmaniak
相关产品推荐
相关产品推荐

