Problem

Mam projekt w Symfony, który ma kilka klas komend (“Command”) będących parserami  (nie ma znaczenia czego w kontekście tego tekstu).  W “AppBundle/Command” są więc klasy wg. schematu nazwy [Nazwa]ParseCommand.php.
Potrzebuję rejestrować te klasy jako serwisy. Do tej pory robiłem to w “services.yml”, np.:

Jednakże nie jest to zbyt wygodne – trzeba pamiętać, żeby zarejestrować serwis przy dodawaniu kolejnego parsera.

Rozwiązanie – service definition object

Rozwiązaniem jest dynamiczne rejestrowanie serwisów przy pomocy service definition object.

Potrzebujemy dodać generowanie serwisów do procesu “kompilowania”.

  1. W klasie “AppBundle/AppBundle.php” (w moim przypadku bundle nazywa się “AppBundle”), dodajemy nowy obiekt klasy odpowiadającej za generowanie serwisów:

     
  2.  Implementujemy klasę “AppBundle/CustomerPass.php”:

    Klasa musi implementować interfejs “CompilerPassInterface” z metodą “process”.
    W moim przykładzie w metodzie tej przy pomocy obiektu klasy “Finder” znajdujemy nazwy wszystkich klas pasujące do naszego wzorca, po czym przepuszczamy ją przez logikę tworzącą “service definition object” (metoda “prepareParserServiceDefinition”).
    Tworzenie definicji to dokładnie ten kod:

    Moje klasy wymagają wywołania metody “setContainer” – jak można zaobserwować na przedstawionym wcześniej fragmencie pliku “services.yml” – odpowiednikiem tego jest wywołanie metody “addMethodCall” na obiekcie definicji serwisu.

Podsumowanie

Przedstawiłem przykład dynamicznego rejestrowania komend jako serwisów w Symfony.