在类体中设置$ this->某些东西,不能使用构造函数依赖注入

时间:2013-09-16 06:22:13

标签: php symfony dependency-injection

我有一个使用data_provider服务的Symfony控制器。我无法弄清楚如何初始化这项服务。

我试过了:

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

导致错误,无法在Controller中使用构造函数,因此留下了:

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. 该文件中的内容解释为here。我不需要在那里做任何事情,因为它是在我创建捆绑包并创建大部分文件时创建的。 (创建捆绑包在标准文档中)

    2

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

    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-&gt; dataProvider。最好是一个取决于开发,生产和测试。

    来依赖注入。将以下内容添加到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网站。文档很好,但没有提到任何破坏它的东西。

3 个答案:

答案 0 :(得分:2)

您应该使用Depency Injection将其注入控制器。

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

的Symfony / SRC / MMT / mrBundle /资源/配置/ services.yml

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

的Symfony / SRC / MMT / mrBundle /控制器/ DefaultController.php

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

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

的Symfony / SRC / MMT / mrBundle /资源/配置/ 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的函数

答案 1 :(得分:1)

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

类似的东西:

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

创建一个扩展Symfony2 Controller的'AdvancedController',将此方法放入其中,让所有控制器扩展它。

在AdvancedController中,您可以将您在控制器中使用的所有全局方法放在一起,这非常舒适。

答案 2 :(得分: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类