1

我对变量的初始化有疑问

我的控制器:

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 中,配置将教义服务传递给我的控制器 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"]]
  • 测试 1 不起作用
  • 带有 ESSAI 1,2,3 (services.yml) 的测试 2 不起作用
  • 测试 3 作品

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

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

我没有在控制器中读取带有实体管理器实例的变量初始化的任何内容。我认为使用 Symfony2.3,TEST 2 可以工作。

我是否忘记了教义配置中的某些内容?

谢谢,

菲尔

4

4 回答 4

3

由于要求是在 ctor 中获得教义,因此您应该像http://symfony.com/doc/current/cookbook/controller/service.html#defining-the-controller-as-a-service一样进行操作:

前端控制器.php

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

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

服务.yml

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

路由.yml

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

作为一种小型的最佳实践方法,我试图将所有控制器作为服务并且从不进行扩展Controller,因为在将容器注入其中时,您会不必要地打开上下文ContainerAware。正如您所看到的那样,单元测试是可能的,而无需使用WebTestCasewhich 有时非常好。

于 2015-10-13T14:12:04.850 回答
1

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

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

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

于 2015-10-13T13:58:42.803 回答
1

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

如果您只需要获取实体管理器的实例,只需按照@scoolnico 所写的方式进行操作,或者如果您真的想将控制器声明为服务,请阅读上面的文档,并且不要打扰ControllerFrameworkBundle 中的类。

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

// src/AppBundle/Controller/HelloController.php
namespace AppBundle\Controller;

use Symfony\Component\HttpFoundation\Response;

class HelloController
{
    private $em;

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

    public function indexAction($name)
    {
        $em = $this->em;
        ...
    }
}

服务.yml:

services:
    app.hello_controller:
        class: AppBundle\Controller\HelloController
        arguments:
            - @doctrine.orm.entity_manager
于 2015-10-13T14:00:43.673 回答
0

当你扩展类Symfony\Bundle\FrameworkBundle\Controller\Controller时,你有很多感兴趣的方法,特别是getDoctrine

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

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

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

于 2015-10-13T13:29:49.927 回答