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:
你可以阅读:
-
more about
_defaults
here - and more about PSR-4 service registration
更多关于_defaults的信息
以及有关PSR-4服务注册的更多信息
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:
你可以阅读:
-
more about
_defaults
here - and more about PSR-4 service registration
更多关于_defaults的信息
以及有关PSR-4服务注册的更多信息
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"