Symfony 5 跨Controller调用getDoctrine()报has() on null错误
错误原因
你直接手动实例化CltvController的行为导致了这个报错:
- 继承自
AbstractController的控制器类依赖Symfony服务容器注入才能正常使用getDoctrine()、getParameter()等继承来的方法 - 你用
new CltvController()创建的实例没有被注入容器,因此实例的$this->container属性为null,调用getDoctrine()时访问null->has()就触发了报错
解决方法
方案1:将公共逻辑抽离为独立服务(最推荐)
不要在控制器中编写可复用的业务逻辑,把计算CLTV的逻辑单独封装成服务,两个控制器都可以注入该服务调用。
步骤:
- 在
src/Service目录下新建CltvCalculator.php,代码示例:
namespace App\Service; use Doctrine\Persistence\ManagerRegistry; use App\Entity\Game; use App\Entity\Adventure; class CltvCalculator { public function __construct(private ManagerRegistry $doctrine) { } public function calculate(string $periodh, string $periodi): float { $em = $this->doctrine->getManager(); $con = $em->getRepository(Game::class); $con3 = $em->getRepository(Adventure::class); $ncnt = $con->findByCountncn($periodh,$periodi); $nadvt = $con3->findByCountadv($periodh,$periodi); return $nadvt[0][0][1]/$ncnt[0][0][1]; } }
- 在
StatLtvcController中注入该服务调用即可:
class StatLtvcController extends AbstractController { public function index(CltvCalculator $cltvCalculator) { $periodh = '2021-06-01'; $periodi = '2021-07-31'; return $this->render('admin/statltvc.html.twig', [ 'cltv_temp' => $cltvCalculator->calculate($periodh, $periodi) ]); } }
- 原
CltvController如果需要保留路由功能,也同样注入该服务调用即可,不需要重复编写计算逻辑。
方案2:从容器获取CltvController实例(不推荐,仅临时修复用)
如果暂时不想重构代码,可以通过容器获取已经完成注入的CltvController实例,而不是手动new:
class StatLtvcController extends AbstractController { public function index() { $cltv_temp = $this->container->get(CltvController::class); return $this->render('admin/statltvc.html.twig', [ 'cltv_temp' => $cltv_temp->cltv() ]); } }
注意:该方案不符合Symfony最佳实践,控制器之间相互调用会提升代码耦合度,仅建议临时修复时使用。
内容的提问来源于stack exchange,提问作者cedric gautier
相关产品推荐
相关产品推荐

