Symfony3.4:如何使用参数指定服务 [英] Symfony3.4: How to specify a service with an argument
问题描述
在Symfony3.4中,支持自动连线时出现如下错误.
如果用$articleType
指定服务名称,以及显示对应文章的现有代码,会出现如下错误.
将多个服务传递给 __construct 不起作用.
有什么好办法吗?
In Symfony3.4, the following error occurred while supporting automatic wiring.
If you specify the service name with $articleType
and the existing code that displays the corresponding article, the following error will occur.
Passing multiple services to __construct doesn't work.
Is there any good way?
https://symfony.com/doc/3.4/service_container/3.3-di-changes.html
控制器.php
https://symfony.com/doc/3.4/service_container/3.3-di-changes.html
Controller.php
private function getArticleSummary($articleType)
{
$summary = array();
$articleService = $this->get('admin.'.$articleType.'Service');
foreach (array('draft', 'pending', 'reject', 'publish', 'hidden') as $articleStatus) {
$params = array(
'articleType' => $articleType,
'articleStatus' => $articleStatus,
);
$summary[$articleStatus] = $articleService->countArticleBySearchParams($params);
}
return $summary;
}
services.yml
services.yml
services:
_defaults:
autowire: true
autoconfigure: true
public: false
App\:
resource: '../../src/*'
exclude: '../../src/{Entity,Repository, Ahi/Sp/AdminBundle/Resources/public/uploadify, Ahi/Sp/AdminBundle/Ahi/Sp/PublicBundle/ }'
App\Ahi\Sp\AdminBundle\Controller\:
resource: '../../src/Ahi/Sp/AdminBundle/Controller'
public: true
tags: ['controller.service_arguments']
admin.brandeventService:
autowire: true
autoconfigure: true
class: 'App\Ahi\Sp\AdminBundle\Model\Service\BrandEventService'
App\Ahi\Sp\AdminBundle\Controller\Hq\DefaultController:
arguments: [ '@admin.brandeventService' ]
App\Ahi\Sp\AdminBundle\Model\Service\BrandEventService: '@admin.brandeventService'
当前代码错误
Service "admin.brandeventService" not found:
even though it exists in the app's container,
the container inside "App\Ahi\Sp\AdminBundle\Controller\Hq\DefaultController"
is a smaller service locator that only knows about the "doctrine"
试过的代码
- 将 $brandEventService 添加到 articleService 的 __construct
- 将 __construct 和 $brandEventService 添加到 DefaultController
- 在 services.yml 中的 DefaultController 中设置服务
- 将 BrandEventService $brandEventService 添加到 getArticleSummary
默认控制器.php
protected $brandEventService;
public function __construct(BrandEventService $brandEventService)
{
$this->brandEventService = $brandEventService;
}
php bin/console debug:container admin.brandeventService
Information for Service "admin.brandeventService"
=================================================
---------------- --------------------------------------------------------
Option Value
---------------- --------------------------------------------------------
Service ID admin.brandeventService
Class App\Ahi\Sp\AdminBundle\Model\Service\BrandEventService
Tags -
Public no
Synthetic no
Lazy no
Shared yes
Abstract no
Autowired yes
Autoconfigured yes
---------------- --------------------------------------------------------
推荐答案
答案基于问题的上下文.这里的目标是将旧版 Symfony 2 应用程序最终更新到 4.4.尝试让代码在 3.4 下运行,而无需重写太多应用程序.
The answer is based on the context of the question. The goal is here is updating a legacy Symfony 2 app ultimately to 4.4. Trying to get the code running under 3.4 without rewriting too much of the app.
基本问题是,在使用 Symfony 的 AbstractController 类时,只能使用 $this->get() 访问特定服务.您可以查看源代码以了解发生了什么,但实际上 ServiceSubscriberInterface::getSubscribedServices() 方法用于指定哪些服务可用.因此,解决此问题的最快方法是将文章类型服务添加到您的派生控制器中:
The basic issue is that when using Symfony's AbstractController class, only specific services can be accessed using $this->get(). You can look at the source code to see what is going on but essentially the ServiceSubscriberInterface::getSubscribedServices() method is used to specify which services are available. So the quickest way to get past this problem is to add the article type services to your derived controller:
class DefaultController extends AbstractController
{
public static function getSubscribedServices() : array
{
$services = parent::getSubscribedServices();
$services['admin.brand'] = BrandEventService::class;
$services['admin.other'] = OtherEventService::class;
return $services;
}
public function type(string $type = null) : Response
{
$serviceId = 'admin.' . $type;
$service = $this->get($serviceId);
return new Response('Article Type ' . $type);
}
上面的代码展示了向控制器的服务定位器添加两个服务,然后在一个动作方法中拉取其中一个.services.yaml 文件只是开箱即用的基本配置.不需要别名或调整.这应该足以让你前进.
The above code shows adding two services to the controller's service locator and then pulling one of them in an action method. The services.yaml file is just the basic out of the box configuration. No aliases or tweaks are needed. It should be enough to get you going.
一旦您了解这里发生了什么,您就可以返回并阅读有关服务定位器的部分,或许可以了解处理此问题的正确"方法.但这实际上可以等到您到达 4.4,因为 Symfony 4 中引入了一些改进.
Once you understand what is going on here then you can go back and read the section on service locators and perhaps understand the 'correct' way of handling this problem. But that could actually wait until you get to 4.4 as there are some refinements introduced in Symfony 4.
这篇关于Symfony3.4:如何使用参数指定服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!