Ленивый сервис загрузки динамически

После просмотра презентации 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 предоставляет способ автоматического добавления тегов в классы, которые реализуют определенный интерфейс: конфигурация службы на основе интерфейса.

Чтобы использовать это, вы должны сделать следующее:

  1. Если у вас его еще нет, создайте интерфейс (например, App\Lens\LensInterface) и пусть ваши классы линз реализуют интерфейс.
  2. В вашем services.yaml файл добавить этот конфиг:
services:
    // ...

    _instanceof:
        App\Lens\LensInterface:
            tags: ['resource.project.lens']

    App\Resource\ProjectResource:
        arguments:
            $lenses: [!tagged resource.project.lens]

    // ...

Затем каждый класс, реализующий ваш объект LensInterface, будет внедрен в ProjectResource без необходимости явной настройки каждого объектива.

Другие вопросы по тегам