在控制器的构造函数中获取一个doctrine实例

时间:2015-10-13 13:16:34

标签: php symfony symfony-2.7

我对变量

的初始化有疑问

我的控制器:

namespace SB\FrontendBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\EntityManager;
use Mie\FrontendBundle\Entity\Product;


class FrontendController extends Controller
{
  protected $em;

  public function __construct(EntityManager $entityManager = null)
  {
    $this->em = $this->getDoctrine()->getManager(); //--->TEST 1

    $this->em = $entityManager; //--->TEST2
  }

  public function dispatchUrl(Request $request)
  {
      $this->em = $this->getDoctrine()->getManager(); //--->TEST 3

      $product = new Product();
      $product->setName('A Foo Bar');
      $product->setPrice('19.99');
      $product->setDescription('Lorem ipsum dolor');


      $this->em->persist($product);
      $this->em->flush();
      die();  
}

}

在我的services.yml中,配置将doctrine服务传递给我的控制器FrontendController

parameters:
    mie.frontend.controller.frontend.class: Mie\FrontendBundle\Controller\FrontendController

services:
# ---> ESSAI 1
    mie.frontend.controller:
        class: "%mie.frontend.controller.frontend.class%"
        arguments:
            - "@doctrine.orm.entity_manager"

# ---> ESSAI 2
    mie.frontend.controller:
        class: "%mie.frontend.controller.frontend.class%"
        arguments: [ @doctrine.orm.entity_manager ]

# ---> ESSAI 3
#    mie.frontend.controller:
#        class: "%mie.frontend.controller.frontend.class%"
#        calls:
#            - [setEntityManager, ["@doctrine.orm.entity_manager"]]
  • TEST 1不起作用
  • TES 2与ESSAI 1,2,3(services.yml)的工作
  • TEST 3的作品

使用TEST 1,我收到以下错误: 错误:调用成员函数has()为null 在vendor \ symfony \ symfony \ src \ Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller.php第291行

使用TEST 2 $ entityManager(__construct的参数)为NULL

我没有读取任何与控制器中的实体初始化的实体操作的初始化。 我认为,使用Symfony2.3,TEST 2可以正常工作。

我是否忘记了学说的配置?

感谢,

菲尔

4 个答案:

答案 0 :(得分:3)

由于要求在ctor中获得原则,你应该像http://symfony.com/doc/current/cookbook/controller/service.html#defining-the-controller-as-a-service那样:

<强> FrontendController.php

<?php
class FrontendController /* extends Controller // no need for this */
{
  /**
   * @var EntityManagerInterface
   */
  protected $em;

  public function __construct(EntityManagerInterface $entityManager) {
    $this->em = $entityManager;
  }
}

<强> services.yml

services:
  front_controller:
    class: ...\FrontendController
    arguments:
      entityManager: "@doctrine.orm.default_entity_manager"

<强>的routing.yml

homepage:
  path: /
  defaults:
    _controller: frontend_controller:yourAction

作为一种小型的最佳实践方法,我尝试将所有控制器作为服务,并且永远不会扩展Controller,因为在将容器注入ContainerAware时会不必要地打开上下文。正如您所看到的那样,单元测试是可能的,而不使用有时相当不错的WebTestCase

答案 1 :(得分:1)

在扩展课程Symfony\Bundle\FrameworkBundle\Controller\Controller时,您有许多感兴趣的方法,特别是getDoctrine

因此,我建议您在需要时直接在控制器操作(实体管理器)内部调用。

    public function dispatchUrl(Request $request)
{
  $this->em = $this->getDoctrine()->getManager();
  ... // your business logic
}

选项3是最好的:没有服务,也没有构造函数。

答案 2 :(得分:1)

你的问题有些令人困惑。看来你有两个相同的服务。目前还不清楚你在做什么样的测试。您是否已将路由配置为使用控制器服务?

无论如何,要将标准框架控制器用作服务,您需要注入容器以及其他服务。 &#34;有&#34;错误似乎表明您正在尝试使用依赖于容器的基本控制器方法之一。注入它很容易:

mie.frontend.controller:
  class: Mie\FrontendBundle\Controller\FrontendController
  calls: [[setContainer, ['@service_container']]]
  arguments:
    - '@doctrine.orm.entity_manager'

基本上,容器负责所有基本功能。使用构造函数注入来注入特定于控制器本身的任何内容。

然后您的路由需要指定服务而不是控制器类。基本上少一个:在_controller参数中。

project_game_export:
  path:     /export
  methods:  [GET,POST]
  defaults:
    _controller: sportacus_project_game_export_controller:exportAction 

http://symfony.com/doc/current/cookbook/controller/service.html

答案 3 :(得分:1)

http://symfony.com/doc/current/cookbook/controller/service.html

如果您只需要获取实体管理器的实例,只需按@scoolnico编写,或者如果您确实要将控制器声明为服务,请阅读上述文档,并且不要打扰{来自FrameworkBundle的{1}}类..

这里的简单示例(从文档中复制并修改):

killall

services.yml:

Controller