0

我有一个使用 data_provider 服务的 Symfony 控制器。我不知道如何初始化此服务。

我试过:

class DefaultController extends Controller {
    public $dataProvider=$this->get('data_provider');

这会导致错误,不能在控制器中使用构造函数,这样我就可以:

public $dataProvider=false;
public function someAction(){
  $this->dataProvider=$this->get('data_provider');
...
public function anotherAction(){
  $this->dataProvider=$this->get('data_provider');
...

所以我每次都必须在控制器动作函数中设置它。创建控制器时是否有一种简单的方法来初始化 dataProvider ?

该服务仅适用于这个包,因此它在 Symfony/src/mmt/myBundle/Resources/config/services.yml 中定义,并且该文件由 Symfony/src/mmt/myBundle/DependencyInjection/myExtension.php 加载。不确定这是否会有所不同,但我更喜欢不需要更改捆绑包外文件的东西。

使用 symfony 2.3.4

[更新]

在看似无穷无尽的指令列表涵盖了不到一半的工作需要做的事情之后,我得到了注射部分的工作。感谢大家给我很好的建议。

  1. 我的服务是我的捆绑包的一部分,并且不想更改捆绑包之外的配置文件来加载它。为了确保 Symfony/src/mmt/mrBundle/Resources/config/services.yml 被加载,你需要一个名为 Symfony/src/mmt/mrBundle/DependencyInjection/mmtmrExtension.php 的文件(不,不要使用任何名称与您的应用程序和捆绑名称相关的 php 文件)。

此处解释了该文件中的内容。我不需要在那里做任何事情,因为它是在我创建捆绑包时创建的,并让它创建大部分文件。(创建捆绑包在标准文档中)

2.

在 services.yml 文件中添加了 data_provider 服务:(阅读有关使用学说设置数据库的标准文档)

data_provider:
    class: mmt\mrBundle\Services\dataProvider
    arguments: [ @doctrine.orm.entity_manager ]

内容:Symfony/src/mmt/mrBundle/Services/dataProvider.php

<?php
namespace mmt\mrBundle\Services;
class dataProvider 
{
    protected $em;
    public function __construct($em){
        $this->em = $em;
    }
    public function getItem($id){
        $item = $this->em->getRepository('mmtmrBundle:Item')
            ->find($id);
        return $item;
    }
    public function saveItem($item){
        $this->em->persist($item);
        $this->em->flush();
    }
}
?>

现在我有了服务,我可以在控制器中使用它,如下所示:

$this->get("data_provider")->getItem(22);

但是我希望我的 DefaultController 在创建 DefaultController 时有一个 $this->dataProvider 。最好是一个取决于 dev、prod 和 test。

引入了依赖注入。将以下内容添加到 Symfony/src/mmt/mrBundle/Resources/config/services.yml

mmt.mr.DefaultController:
     class: mmt\mrBundle\Controller\DefaultController
     arguments: [@data_provider]
     calls: 
         - [ "setContainer", [ @service_container ] ]

现在在您的路线中使用 mmt.mr.DefaultController:indexAction(不要使用 mmtmrBundle:Default:index):

/var/www/html/Symfony/src/mmt/mrBundle/Resources/config/routing.yml

mmtmr_homepage:
    path:  /{id}
    requirements:
      id: \d+
    defaults: { _controller: mmt.mr.DefaultController:indexAction, id: false }

在 Symfony/src/mmt/mrBundle/Controller/DefaultController.php 中应该是这样的:

<?php
namespace mmt\mrBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Session\Session;
class DefaultController extends Controller {
    public $dataProvider;
    public function __construct($data_provider){
        $this->dataProvider = $data_provider;
    }
    public function indexAction($id) {
        $item=$this->dataProvider->getItem($id);
        return $this->render('mmtmrBundle:Default:index.html.twig', 
                array('item' => $item));
    }
}
?>

我想就是这样,缺少的东西请告诉我。恭喜; 您现在知道如何注入依赖项(如果您还没有)。坏消息是,当您阅读本文时,它可能已经过时,您必须访问 Symfony 站点。那里的文档很好,但没有提到任何对我造成破坏的事情。

4

3 回答 3

2

您应该使用依赖注入将其注入控制器。

根据您问题中的课程,您可以执行以下操作:

Symfony/src/mmt/mrBundle/Resources/config/services.yml

   mmt.mr.DefaultController:
         class: mmt\mrBundle\Controller\DefaultController
         calls: 
             - [ setContainer, [ @service_container ] ]
             - [ setDataProvider, [ @data_provider ] ]

Symfony/src/mmt/mrBundle/Controller/DefaultController.php

public function setDataProvider($provider){
    if($this->dataProvider===false){
        $this->dataProvider=$provider;
    }
}

确保使用服务名称,然后使用路由器中的操作,例如:

Symfony/src/mmt/mrBundle/Resources/config/routing.yml

mmtmr_homepage:
    path:  /{id}
    requirements:
      id: \d+
    defaults: { _controller: mmt.mr.DefaultController:indexAction, id: false }

mmt.mr.DefaultController是 services.yml 中使用的名称,:indexAction是 DefaultController.php 中名为 indexAction 的函数

于 2013-09-16T06:39:22.833 回答
1

我建议使用返回服务的方法。

就像是:

public function getDataProvider()
{
    return $this->get('data_provider');
}

并创建一个扩展 Symfony2 控制器的“AdvancedController”,把这个方法放进去,让你所有的控制器扩展它。

在 AdvancedController 中,您可以将您使用的所有全局方法放入控制器中,这真的很舒服。

于 2013-09-16T06:42:33.080 回答
0

使用依赖注入后,$data_provider 必须正确地提供给您的控制器,所以为什么不使用它:

public function dataInit($data_provider){
  $logger = $this->get('logger');
  $logger->notice('from dataInit so this works');
}

也许它必须是:

public function dataInit($data_provider){
  $logger = $data_provider->getLogger();
  $logger->notice('from dataInit so this works');
}

如果没有,请粘贴您的 dataProvider 类

于 2013-09-16T10:27:16.767 回答