在controller的构造函数中获取一个doctrine的实例
Get an instance of doctrine in the constructor of controller
我对变量的初始化有疑问
我的控制器:
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 有效
在测试 1 中,出现以下错误:
错误:在 null 上调用成员函数 has()
在 vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Controller\Controller.php 中第 291
行
有测试 2
$entityManager(__construct 的参数)为 NULL
我没有读到任何反对在控制器中使用 entitymanager 实例初始化变量的内容。
使用 Symfony2.3,我认为 TEST 2 有效。
我是不是忘了配置 doctrine 的东西了?
谢谢,
菲尔
当您扩展 class Symfony\Bundle\FrameworkBundle\Controller\Controller
时,您有许多感兴趣的方法,特别是 getDoctrine
。
因此,我建议您在需要时直接在控制器操作内部调用实体管理器。
public function dispatchUrl(Request $request)
{
$this->em = $this->getDoctrine()->getManager();
... // your business logic
}
选项 3 是最好的:没有服务,也没有构造函数。
你的问题有点令人费解。您似乎有两个相同的服务。也不清楚你在做什么测试。您是否已将路由配置为使用控制器服务?
无论如何,要将标准框架控制器用作服务,您需要注入容器以及其他服务。 "has" 错误似乎表明您正在尝试使用依赖于容器的基本控制器方法之一。注入它很容易:
mie.frontend.controller:
class: Mie\FrontendBundle\Controller\FrontendController
calls: [[setContainer, ['@service_container']]]
arguments:
- '@doctrine.orm.entity_manager'
基本上,容器负责所有基本功能。使用构造函数注入来注入任何特定于控制器本身的东西。
然后你的路由需要指定服务而不是控制器class。基本上少了一个:在_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
http://symfony.com/doc/current/cookbook/controller/service.html
如果你只需要获取实体管理器的实例,就按照@scoolnico 写的那样做,或者如果你真的想将你的控制器声明为服务,请阅读上面的文档,不要打扰Controller
class 来自 FrameworkBundle..
此处为简单示例(从文档中复制并修改):
// 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;
...
}
}
services.yml:
services:
app.hello_controller:
class: AppBundle\Controller\HelloController
arguments:
- @doctrine.orm.entity_manager
因为要求是在 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
,这有时非常好。
我对变量的初始化有疑问
我的控制器:
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 有效
在测试 1 中,出现以下错误: 错误:在 null 上调用成员函数 has() 在 vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Controller\Controller.php 中第 291
行有测试 2 $entityManager(__construct 的参数)为 NULL
我没有读到任何反对在控制器中使用 entitymanager 实例初始化变量的内容。 使用 Symfony2.3,我认为 TEST 2 有效。
我是不是忘了配置 doctrine 的东西了?
谢谢,
菲尔
当您扩展 class Symfony\Bundle\FrameworkBundle\Controller\Controller
时,您有许多感兴趣的方法,特别是 getDoctrine
。
因此,我建议您在需要时直接在控制器操作内部调用实体管理器。
public function dispatchUrl(Request $request)
{
$this->em = $this->getDoctrine()->getManager();
... // your business logic
}
选项 3 是最好的:没有服务,也没有构造函数。
你的问题有点令人费解。您似乎有两个相同的服务。也不清楚你在做什么测试。您是否已将路由配置为使用控制器服务?
无论如何,要将标准框架控制器用作服务,您需要注入容器以及其他服务。 "has" 错误似乎表明您正在尝试使用依赖于容器的基本控制器方法之一。注入它很容易:
mie.frontend.controller:
class: Mie\FrontendBundle\Controller\FrontendController
calls: [[setContainer, ['@service_container']]]
arguments:
- '@doctrine.orm.entity_manager'
基本上,容器负责所有基本功能。使用构造函数注入来注入任何特定于控制器本身的东西。
然后你的路由需要指定服务而不是控制器class。基本上少了一个:在_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
http://symfony.com/doc/current/cookbook/controller/service.html
如果你只需要获取实体管理器的实例,就按照@scoolnico 写的那样做,或者如果你真的想将你的控制器声明为服务,请阅读上面的文档,不要打扰Controller
class 来自 FrameworkBundle..
此处为简单示例(从文档中复制并修改):
// 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;
...
}
}
services.yml:
services:
app.hello_controller:
class: AppBundle\Controller\HelloController
arguments:
- @doctrine.orm.entity_manager
因为要求是在 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
,这有时非常好。