Как управлять общими зависимостями с родительскими сервисами
Как управлять общими зависимостями с родительскими сервисами
По мере добавление функционала в ваше приложение, вы также можете заиметь
родственные классы, которые имеют некоторые общие зависимости. Например,
вы можете иметь несколько классов хранилища, которым нужен сервис
doctrine.entity_manager
и необязательный сервисlogger
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
// src/AppBundle/Repository/BaseDoctrineRepository.php
namespace AppBundle\Repository;
// ...
abstract class BaseDoctrineRepository
{
protected $entityManager;
protected $logger;
public function __construct(EntityManagerInterface $manager)
{
$this->entityManager = $manager;
}
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
}
// ...
}
Так же, как вы используете наследование PHP, чтобы избежать дубликатов в вашем PHP-коде, сервис-контейнер позволяет вам расширить родительские сервисы, чтобы избежать дубликатов определений сервиса:
- YAML
- XML
- PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
services:
AppBundle\Repository\BaseDoctrineRepository:
abstract: true
arguments: ['@doctrine.entity_manager']
calls:
- [setLogger, ['@logger']]
AppBundle\Repository\DoctrineUserRepository:
# расширить сервис AppBundle\Repository\BaseDoctrineRepository
parent: AppBundle\Repository\BaseDoctrineRepository
AppBundle\Repository\DoctrinePostRepository:
parent: AppBundle\Repository\BaseDoctrineRepository
# ...
В этом контексте, наличие сервиса parent
предполагает, что аргументы и
вызовы метода родительского сервиса должны быть использованы для дочерних
сервисов. В особенности, EntityManager
будет внедрён, а setLogger()
будет вызван, когда будет инстанциирован AppBundle\Repository\DoctrineUserRepository
.
Все атрибуты родительского сервиса являются общими с дочерним, кроме
shared
, abstract
и tags
. Они не наследуются от родителя.
Note
Если у вас есть раздел _defaults
в вашем файле, все дочерние сервисы
должны ясно переопределять эти значения, чтобы избежать двусмысленности.
Вы увидите чёткое сообщение ошибки об этом.
Tip
В показанных примерах, класс, которые имеют общую конфигурацию, ткакже расширяются из одного родительского класса в PHP. Это вовсе не обязательно. Вы можете просто извлечь общие части схожих определений сервиса в родительский сервис, не расширяя также родительский класс в PHP.
Переопределение родительских зависимостей
Могут быть времена, когда вы захотите переопределить то, какой сервис внедряется только для одного из дочерних сервисов. Вы можете пеоепределить болошиниство настроек просто указав их в дочернем классе:
- YAML
- XML
- PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
services:
# ...
AppBundle\Repository\DoctrineUserRepository:
parent: AppBundle\Repository\BaseDoctrineRepository
# переопределяет публичную настройку родительского сервиса
public: false
# добавляет аргумент '@app.username_checker' к родительскому
# списку аргументов
arguments: ['@app.username_checker']
AppBundle\Repository\DoctrinePostRepository:
parent: AppBundle\Repository\BaseDoctrineRepository
# переопределяет первый аргумент (используя специальный ключ index_N)
arguments:
index_0: '@doctrine.custom_entity_manager'