Symfony2 - 使用Controller实现自动装配服务

时间:2022-10-25 16:52:41

I am able to use the new autowire feature of Symfony2 to inject a service into a service. However, I cannot inject a service into a controller. What am I not doing/doing wrong?

我能够使用Symfony2的新autowire功能将服务注入服务。但是,我无法将服务注入控制器。我不做什么/做错了什么?

This is my services.yml file:

这是我的services.yml文件:

services:
    home_controller:
        class:  AppBundle\Controller\HomeController
        autowire:  true

This is my ServiceConsumerDemo:

这是我的ServiceConsumerDemo:

namespace AppBundle\Services;

class ServiceConsumerDemo {

    private $serviceDemo;

    public function __construct(ServiceDemo $serviceDemo) {
        $this->serviceDemo = $serviceDemo;
    }

    public function getMessage(){
        return $this->serviceDemo->helloWorld();
    }
}

This is ServiceDemo:

这是ServiceDemo:

namespace AppBundle\Services;

class ServiceDemo 
{    
    public function helloWorld(){
        return "hello, world!";
    }
}

This is HomeController (which works):

这是HomeController(可以工作):

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;


class HomeController extends Controller
{
    /**
     * @Route("/")
     *
     */
    public function indexAction(Request $request)
    {
        $message[0] = $this->get('service_consumer_demo')->getMessage();
        return new \Symfony\Component\HttpFoundation\JsonResponse($message);
    }
}

This is HomeController which does not work

这是HomeController不起作用

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Services\ServiceConsumerDemo;

class HomeController extends Controller
{

    private $serviceConsumerDemo;

    public function __construct(ServiceConsumerDemo $serviceConsumerDemo) {

        $this->serviceConsumerDemo = $serviceConsumerDemo;
    }

    /**
     * @Route("/", name="homepage")
     *
     */
    public function indexAction(Request $request)
    {
        $message[0] =  $this->serviceConsumerDemo->getMessage();
        return new \Symfony\Component\HttpFoundation\JsonResponse($message);
    }
}

This is the error thrown:

这是抛出的错误:

Catchable Fatal Error: Argument 1 passed to AppBundle\Controller\HomeController::__construct() must be an instance of AppBundle\Services\ServiceConsumerDemo, none given,

可捕获致命错误:传递给AppBundle \ Controller \ HomeController :: __ construct()的参数1必须是AppBundle \ Services \ ServiceConsumerDemo的实例,没有给出,

How do I access the Services in the Controller? I understand I need to declare the controller as a service. So I'm mentioning the controller in the services.yml file. Is there anything else that I need to do?

如何访问Controller中的服务?我知道我需要将控制器声明为服务。所以我在services.yml文件中提到了控制器。还有什么我需要做的吗?

3 个解决方案

#1


1  

By default, controllers are not considered as services, so you can't use autowiring with them.

默认情况下,控制器不被视为服务,因此您无法使用它们进行自动装配。

However, it's a simple enough fix - add a @Route annotation on the class (i.e. not on an action method in the class) with a service definition.

但是,这是一个简单的修复 - 使用服务定义在类上添加@Route注释(即不在类中的操作方法上)。

From the documentation:

从文档:

The @Route annotation on a controller class can also be used to assign the controller class to a service so that the controller resolver will instantiate the controller by fetching it from the DI container instead of calling new PostController() itself.

控制器类上的@Route注释也可用于将控制器类分配给服务,以便控制器解析器通过从DI容器中取出控制器来实例化控制器,而不是调用新的PostController()本身。

For example:

/** 
 * @Route(service="app_controller") 
 */
class AppController extends Controller
{

    private $service;

    public function __construct(SomeService $service)
    {
        $this->service = $service;
    }

    /** @Route("/") */
    public function someAction()
    {
        $this->service->doSomething();
    }

}

and in your config:

并在您的配置中:

app_controller:
    class:  AppBundle\Controller\AppController
    autowire: true

#2


1  

Symfony 3.3+ May 2017 UPDATE!

Symfony 3.3 allows native way to approach this.

Symfony 3.3允许本地方式来实现这一点。

# app/config/services.yml
services:
    _defaults:
        autowire: true # all services in this config are now autowired

    App\: # no more manual registration of similar groups of services 
        resource: ../{Controller}

This means App\Controller\SomeController is autowired by default and to be found in app/Controller/SomeController.php file.

这意味着默认情况下App \ Controller \ SomeController是自动装配的,可以在app / Controller / SomeController.php文件中找到。

You can read:

你可以阅读:


Thanks to autowiring in Symfony 2.8+ I could create bundle, that adds autowiring even for controllers: Symplify/ControllerAutowire

感谢Symfony 2.8+中的自动装配,我可以创建捆绑包,即使对于控制器也可以添加自动装配:Symplify / ControllerAutowire

You can read more about this in the article.

您可以在文章中阅读更多相关信息。

Usage is as simple as:

用法很简单:

class YourController
{
    public function __construct(SomeDependency $someDependency)
    {
        // ...
    }
}

Nothing more is required.

不需要更多。

#3


-1  

You do not pass service to your controller in services.yml. Change it to:

您没有将服务传递给services.yml中的控制器。将其更改为:

services:
    service_demo:
        class:  AppBundle\Services\ServiceDemo
    service_consumer_demo:
        class:  AppBundle\Services\ServiceConsumerDemo
        autowire:   true
    home_controller:
        class:  AppBundle\Controller\HomeController
        autowire:  true
        arguments:
            service: "@service_consumer_demo"

#1


1  

By default, controllers are not considered as services, so you can't use autowiring with them.

默认情况下,控制器不被视为服务,因此您无法使用它们进行自动装配。

However, it's a simple enough fix - add a @Route annotation on the class (i.e. not on an action method in the class) with a service definition.

但是,这是一个简单的修复 - 使用服务定义在类上添加@Route注释(即不在类中的操作方法上)。

From the documentation:

从文档:

The @Route annotation on a controller class can also be used to assign the controller class to a service so that the controller resolver will instantiate the controller by fetching it from the DI container instead of calling new PostController() itself.

控制器类上的@Route注释也可用于将控制器类分配给服务,以便控制器解析器通过从DI容器中取出控制器来实例化控制器,而不是调用新的PostController()本身。

For example:

/** 
 * @Route(service="app_controller") 
 */
class AppController extends Controller
{

    private $service;

    public function __construct(SomeService $service)
    {
        $this->service = $service;
    }

    /** @Route("/") */
    public function someAction()
    {
        $this->service->doSomething();
    }

}

and in your config:

并在您的配置中:

app_controller:
    class:  AppBundle\Controller\AppController
    autowire: true

#2


1  

Symfony 3.3+ May 2017 UPDATE!

Symfony 3.3 allows native way to approach this.

Symfony 3.3允许本地方式来实现这一点。

# app/config/services.yml
services:
    _defaults:
        autowire: true # all services in this config are now autowired

    App\: # no more manual registration of similar groups of services 
        resource: ../{Controller}

This means App\Controller\SomeController is autowired by default and to be found in app/Controller/SomeController.php file.

这意味着默认情况下App \ Controller \ SomeController是自动装配的,可以在app / Controller / SomeController.php文件中找到。

You can read:

你可以阅读:


Thanks to autowiring in Symfony 2.8+ I could create bundle, that adds autowiring even for controllers: Symplify/ControllerAutowire

感谢Symfony 2.8+中的自动装配,我可以创建捆绑包,即使对于控制器也可以添加自动装配:Symplify / ControllerAutowire

You can read more about this in the article.

您可以在文章中阅读更多相关信息。

Usage is as simple as:

用法很简单:

class YourController
{
    public function __construct(SomeDependency $someDependency)
    {
        // ...
    }
}

Nothing more is required.

不需要更多。

#3


-1  

You do not pass service to your controller in services.yml. Change it to:

您没有将服务传递给services.yml中的控制器。将其更改为:

services:
    service_demo:
        class:  AppBundle\Services\ServiceDemo
    service_consumer_demo:
        class:  AppBundle\Services\ServiceConsumerDemo
        autowire:   true
    home_controller:
        class:  AppBundle\Controller\HomeController
        autowire:  true
        arguments:
            service: "@service_consumer_demo"

相关文章