Ленивый сервис загрузки динамически
После просмотра презентации Laravell Nova я захотел создать функциональность, аналогичную линзам, в своем собственном приложении.
У меня есть следующие понятия:
- Сущность: стандартная доктрина
- Ресурс: класс, который описывает ресурс, включая целевую сущность и доступные линзы.
- Объектив: есть метод
apply(Request $request, QueryBuilder $qb)
которые позволяют вам изменятьQueryBuilder
на основеRequest
,
Цель состоит в том, чтобы определить все Lenses
как услуга, а затем как-то назначить их Resource
, Это проблема, которую я пытаюсь решить.
Попытка 1: напрямую ввести Lenses
в ресурс
ProjectResource.php
<?php
class ProjectResource
{
protected $lenses = [];
public function __construct(
ProjectRepository $repository,
LensInterface $activeProjectLens,
LensInterface $starredProjectLens
) {
$this->lenses = [
$activeProjectLens,
$starredProjectLens
];
}
public function getLenses() {
return $this->lenses;
}
}
Недостатком этого является то, что каждый Lens
сервис создается и должен быть определен вручную
Попытка 2: добавить тег Lenses
в ресурс
В моем services.yaml
пометьте службы и назначьте их в качестве аргумента ресурса:
App\Lens\ActiveProjectLens:
tags: ['resource.project.lens']
App\Lens\StarredProjectLens:
tags: ['resource.project.lens']
App\Resource\ProjectResource:
arguments:
$lenses: !tagged resource.project.lens
ProjectResource.php
<?php
class ProjectResource
{
protected $lenses = [];
public function __construct(
ProjectRepository $repository,
iterable $lenses
) {
$this->lenses = $lenses;
}
public function getLenses() {
return $this->lenses;
}
}
Недостатком этого подхода является каждый Lens
service и Resource должны быть помечены и не могут быть автоматически настроенной службой.
** Попытка 3: добавить проход компилятора **
Я попытался добавить process()
метод к Kernel
но я не зашел слишком далеко с этим.
Моя цель - как-то определить список услуг в Resource
и им вводят. Есть ли установленный шаблон для этого?
1 ответ
Ваш подход с тегами кажется хорошим. Symfony предоставляет способ автоматического добавления тегов в классы, которые реализуют определенный интерфейс: конфигурация службы на основе интерфейса.
Чтобы использовать это, вы должны сделать следующее:
- Если у вас его еще нет, создайте интерфейс (например,
App\Lens\LensInterface
) и пусть ваши классы линз реализуют интерфейс. - В вашем
services.yaml
файл добавить этот конфиг:
services:
// ...
_instanceof:
App\Lens\LensInterface:
tags: ['resource.project.lens']
App\Resource\ProjectResource:
arguments:
$lenses: [!tagged resource.project.lens]
// ...
Затем каждый класс, реализующий ваш объект LensInterface, будет внедрен в ProjectResource без необходимости явной настройки каждого объектива.