在symfony2 Controller中注入服务

时间:2013-09-03 14:14:55

标签: symfony dependency-injection

如何将服务(我创建的服务)注入控制器? 设定者注射就可以了。

<?php
namespace MyNamespace;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class MyController extends Controller
{
    public function setMyService(MyService $myService)
    {
        $this->myService = $myService;
    }

    public function indexAction()
    {
        //Here I cannot access $this->myService;
        //Because the setter is not called magically!
    }
}

我的路线设置:

// Resources/routing.yml
myController_index:
    pattern:  /test
    defaults: { _controller: "FooBarBundle:MyController:index" }

我正在另一个包中设置服务:

// Resources/services.yml 
parameters:
   my.service.class: Path\To\My\Service

services:
    my_service:
        class: %my.service.class%

当路线解决时,不会注入服务(我知道不应该)。 我想在yml文件中的某个地方,我必须设置:

    calls:
        - [setMyService, [@my_service]]

我没有将此Controller用作服务,它是一个为请求提供服务的常规控制器。

编辑:此时,我正在使用$ this-&gt; container-&gt; get('my_service');但我需要注射它。

4 个答案:

答案 0 :(得分:7)

如果要将服务注入控制器,则必须define controllers as services

您还可以查看JMSDiExtraBundle的special handling of controllers - 如果这样可以解决您的问题。但是因为我将控制器定义为服务,所以我没试过。

答案 1 :(得分:6)

使用JMSDiExtraBundle时, DON&#39; T 必须将您的控制器定义为服务(与@elnur不同),代码为:

<?php

namespace MyNamespace;

use JMS\DiExtraBundle\Annotation as DI;
use Path\To\My\Service;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class MyController extends Controller
{
    /**
     * @var $myService Service
     *
     * @DI\Inject("my_service")
     */
    protected $myService;

    public function indexAction()
    {
        // $this->myService->method();
    }
}

我发现这种方法非常好,因为你避免编写__construct()方法。

答案 2 :(得分:3)

因为现在是2017年结束,并且没有Symfony 3或即将推出的Symfony 4的标签(我认为不应该这样),这个问题可以通过本地更好的方式解决。

如果你仍然在努力并且不知何故在这个页面上而不是在Symfony文档中,那么你应该知道,你不需要将控制器声明为服务,如it is already registered as one

您需要做的是检查services.yml

# app/config/services.yml
services:
    # default configuration for services in *this* file
    _defaults:
        # ...
        public: false

如果您希望所有服务都公开,请将public: false更改为public:true

或明确添加服务并将其声明为公开:

# app/config/services.yml
services:
    # ... same code as before

    # explicitly configure the service
    AppBundle\Service\MessageGenerator:
        public: true

然后在您的控制器中,您可以获得服务:

use AppBundle\Service\MessageGenerator;

// accessing services like this only works if you extend Controller
class ProductController extends Controller
{
    public function newAction()
    {
        // only works if your service is public
        $messageGenerator = $this->get(MessageGenerator::class);
    }
}

了解更多:

答案 3 :(得分:0)

如果您不想将控制器定义为服务,则可以在 kernel.controller 事件中添加一个侦听器,以便在执行之前对其进行配置。这样,您可以使用setter在控制器中注入所需的服务。

http://symfony.com/doc/current/components/http_kernel/introduction.html#component-http-kernel-kernel-controller