我正在将 Symfony 3.2 项目迁移到 Symfony 3.3,并且我想使用DI 新功能。我已经阅读了文档,但到目前为止我可以让它工作。请参阅以下类定义:
use Http\Adapter\Guzzle6\Client;
use Http\Message\MessageFactory;
abstract class AParent
{
protected $message;
protected $client;
protected $api_count_url;
public function __construct(MessageFactory $message, Client $client, string $api_count_url)
{
$this->message = $message;
$this->client = $client;
$this->api_count_url = $api_count_url;
}
public function getCount(string $source, string $object, MessageFactory $messageFactory, Client $client): ?array
{
// .....
}
abstract public function execute(string $source, string $object, int $qty, int $company_id): array;
abstract protected function processDataFromApi(array $entities, int $company_id): array;
abstract protected function executeResponse(array $rows = [], int $company_id): array;
}
class AChildren extends AParent
{
protected $qty;
public function execute(string $source, string $object, int $qty, int $company_id): array
{
$url = $this->api_count_url . "src={$source}&obj={$object}";
$request = $this->message->createRequest('GET', $url);
$response = $this->client->sendRequest($request);
}
protected function processDataFromApi(array $entities, int $company_id): array
{
// ....
}
protected function executeResponse(array $rows = [], int $company_id): array
{
// ....
}
}
这是我的app/config/services.yml
文件的样子:
parameters:
serv_api_base_url: 'https://url.com/api/'
services:
_defaults:
autowire: true
autoconfigure: true
public: false
CommonBundle\:
resource: '../../src/CommonBundle/*'
exclude: '../../src/CommonBundle/{Entity,Repository}'
CommonBundle\Controller\:
resource: '../../src/CommonBundle/Controller'
public: true
tags: ['controller.service_arguments']
# Services that need manually wiring: API related
CommonBundle\API\AParent:
arguments:
$api_count_url: '%serv_api_base_url%'
但我收到以下错误:
AutowiringFailedException 无法自动装配服务“CommonBundle\API\AChildren”:方法“__construct()”的参数“$api_count_url”必须具有类型提示或显式指定值。
当然,我在这里遗漏了一些东西,或者根本不可能,这导致我想到下一个问题:这是一个糟糕的 OOP 设计还是 Symfony 3.3 DI 特性中缺少的功能?
当然,我不想让AParent
类成为接口,因为我不想重新定义实现此类接口的类的方法。
此外,我不想重复自己并将相同的功能复制/粘贴到孩子身上。
想法?线索?建议?这可能吗?
更新
阅读“如何使用父服务管理公共依赖项”后,我在我的场景中尝试了以下内容:
CommonBundle\API\AParent:
abstract: true
arguments:
$api_count_url: '%serv_api_base_url%'
CommonBundle\API\AChildren:
parent: CommonBundle\API\AParent
arguments:
$base_url: '%serv_api_base_url%'
$base_response_url: '%serv_api_base_response_url%'
但是错误变成了:
当设置了“父级”时,服务“CommonBundle\API\AChildren”的属性“autowire”不能从“_defaults”继承。将您的子定义移动到单独的文件或在 /var/www/html/oneview_symfony/app/config/services.yml 中明确定义此属性(从“/var/www/html/oneview_symfony/app/config/ config.yml”)。
但是我可以使它与以下设置一起工作:
CommonBundle\API\AParent:
arguments:
$api_count_url: '%serv_api_base_url%'
CommonBundle\API\AChildren:
arguments:
$api_count_url: '%serv_api_base_url%'
$base_url: '%serv_api_base_url%'
$base_response_url: '%serv_api_base_response_url%'
这是正确的方法吗?这有意义吗?
更新#2
按照@Cerad 的说明,我做了一些模组(见上面的代码,见下面的定义),现在对象来了NULL
?任何想法为什么会这样?
// services.yml
services:
CommonBundle\EventListener\EntitySuscriber:
tags:
- { name: doctrine.event_subscriber, connection: default}
CommonBundle\API\AParent:
abstract: true
arguments:
- '@httplug.message_factory'
- '@httplug.client.myclient'
- '%ser_api_base_url%'
// services_api.yml
services:
CommonBundle\API\AChildren:
parent: CommonBundle\API\AParent
arguments:
$base_url: '%serv_api_base_url%'
$base_response_url: '%serv_api_base_response_url%'
// config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
- { resource: services_api.yml }
为什么对象NULL
在子类中?