Як управляти спільними залежностями з батьківськими сервісами
Дата оновлення перекладу 2024-06-04
Як управляти спільними залежностями з батьківськими сервісами
За мірою додавання функціоналу у ваш додаток, ви також можете стати власником
споріднених класів, які мають деякі спільні залежності. Наприклад, ви можете
мати декілька класів сховища, яким потрібен сервіс doctrine.orm.entity_manager
та необовʼязковий сервіс logger
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// src/Repository/BaseDoctrineRepository.php
namespace App\Repository;
use Doctrine\ORM\EntityManager;
use Psr\Log\LoggerInterface;
// ...
abstract class BaseDoctrineRepository
{
protected LoggerInterface $logger;
public function __construct(
protected EntityManager $entityManager,
) {
}
public function setLogger(LoggerInterface $logger): void
{
$this->logger = $logger;
}
// ...
}
Ваші класи дочірнього сервісу можуть виглядати так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
// src/Repository/DoctrineUserRepository.php
namespace App\Repository;
use App\Repository\BaseDoctrineRepository;
// ...
class DoctrineUserRepository extends BaseDoctrineRepository
{
// ...
}
// src/Repository/DoctrinePostRepository.php
namespace App\Repository;
use App\Repository\BaseDoctrineRepository;
// ...
class DoctrinePostRepository extends BaseDoctrineRepository
{
// ...
}
Сервіс-контейнер дозволяє вам розширрювати батьківські сервіси для того, щоб уникнути дубльованих визначень сервісів:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# config/services.yaml
services:
App\Repository\BaseDoctrineRepository:
abstract: true
arguments: ['@doctrine.orm.entity_manager']
calls:
- setLogger: ['@logger']
App\Repository\DoctrineUserRepository:
# розширити сервіс App\Repository\BaseDoctrineRepository
parent: App\Repository\BaseDoctrineRepository
App\Repository\DoctrinePostRepository:
parent: App\Repository\BaseDoctrineRepository
# ...
У цьому контексті, наявність сервісу parent
передбачає, що аргументи і виклики
методу батьківського сервісу повинні бути використані для дочірніх сервісів. А точніше,
EntityManager
буде впроваджений, а setLogger()
буде викликаний, коли буде
інстанційовано App\Repository\DoctrineUserRepository
.
Всі атрибути батьківського сервісу є спільними з дочірніми, окрім shared
,
abstract
і tags
. Вони не успадковуються від батька.
Tip
У продемонстрованих прикладах, класи, які мають спільну конфігурацію, також розширюються з одного батьківського класу у PHP. Це зовсім не обовʼязково. Ви можете просто вилучити спільні частини схожих визначень сервісу у батьківський сервіс, не розширюючи також батьківський клас у PHP.
Перевизначення батьківських залежностей
Можуть бути випадки, коли ви захочете перевизначити те, який сервіс впроваджується тільки для одного з дочірніх сервісів. Ви можете перевизначити більшість налаштувань, просто вказавши їх у дочірньому класі:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# config/services.yaml
services:
# ...
App\Repository\DoctrineUserRepository:
parent: App\Repository\BaseDoctrineRepository
# перевизначає приватне налаштування батьківського сервісу
public: true
# додає аргумент '@app.username_checker' до батьківського
# списку аргументів
arguments: ['@app.username_checker']
App\Repository\DoctrinePostRepository:
parent: App\Repository\BaseDoctrineRepository
# перевизначає перший аргумент (використовуючи спеціальний ключ index_N)
arguments:
index_0: '@doctrine.custom_entity_manager'