【发布时间】:2013-09-16 06:22:13
【问题描述】:
我有一个使用 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
[更新]
在看似无穷无尽的指令列表中,只涵盖了您需要做的不到一半的指令,我让注射部分开始工作。感谢大家给我很好的建议。
我的服务是我的捆绑包的一部分,不想更改捆绑包之外的配置文件来加载它。为了确保 Symfony/src/mmt/mrBundle/Resources/config/services.yml 被加载,你需要一个名为 Symfony/src/mmt/mrBundle/DependencyInjection/mmtmrExtension.php 的文件(不,不要使用任何名称与您的应用程序和捆绑名称相关的 php 文件)。
解释了该文件中的内容here。我不需要在那里做任何事情,因为它是在我创建捆绑包时创建的,并让它创建大部分文件。 (创建捆绑包在标准文档中)
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 站点。那里的文档很好,但没有提到任何对我造成破坏的事情。
【问题讨论】:
-
您确定您将
routing.yml定义为{ _controller: m.y.DefaultController:indexAction }并清除了缓存吗? -
@touki 更改了路由器,现在调用了该方法(选择在 services.yml 中调用)。因为这给了我一个错误,所以我添加了 __construct 函数但得到了同样的错误:
Error: Call to a member function get() on a non-object in /var/www/html/Symfony/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php line 252 -
是的,您需要在服务声明中添加
calls: [ "setContainer", [ @service_container ] ],以便将服务容器注入控制器。 -
@Touki 根据文档再次选择了构造函数,但看起来在动作函数和构造函数中 $this 指的是 DefaultController 以外的东西。尝试在构造函数中设置 $DataSource:
$this->$dataProvider = $data_provider;导致Cannot access empty property将其留空是没有用的,因为整个练习的重点是设置 $this->dataProvider -
@Touki 抱歉,忘记了
$this->$dataProvider不是有效的 PHP 访问属性。
标签: php symfony dependency-injection