Wpis z mikrobloga

Pytanie dotyczące Symfony i obiektowości w PHP. Robię na studia prosty system ticketowy, do którego trafiają zgłoszenia z maila. Są encje Ticket i Mail, kontrolery TicketController i MailController (do niego z zewnątrz wpadają maile) i klasy pomocnicze TicketModel i MailModel, wywoływane z Service Container.

Chciałbym, żeby:
- funkcja przyjmująca maila w MailModel mogła wywołać funkcję dodawania ticketa w TicketModel
- funkcja dodająca odpowiedź do ticketa od konsultanta w TicketModel, mogła wywołać wysyłkę maila z odpowiedzią z MailModel

Niestety po zrobieniu zależności dostaję "Circular reference detected for service...".

Jak Wy, programiści za 15k, byście to zaprogramowali?

#symfony #php
  • 11
@NiktNieTroszczy:

taki zapis:

ticketModel:
class: Model\TicketModel
arguments: [@mailModel]

mailModel:
class: Model\MailModel
arguments: [@ticketModel]

wywala

Circular reference detected for service...


i pytanie jest takie jak to inaczej ładnie rozplanować
@Harry19911: jeżeli to rzeczywiście ma sens a wątpie (wydaje mi się że dwie klasy nie powinny tak mocno zależeć od siebie, raczej nie jest to zgodne z single responsibility principle), to stworzyłbym customową fabrykę

http://symfony.com/doc/current/components/dependency_injection/factories.html

ewentualnie service zwykł który przyjmuje container z metodami do tworzenia ticketu i mail

wydaje mi się że powinno to zadziałąć ale jeszcze mi się nie zażyło żeby trzeba tak było robić.
@NiktNieTroszczy: już kiedyś tak robiłem że do takiej problematycznego service z poziomu kontrolera wstrzykiwałem inny service. Teraz chciałem się dowiedzieć jak się tego unika

@Jaslanin:

jeżeli to rzeczywiście ma sens a wątpie

skoro nie działa to się domyśliłem że nie ma sensu ( ͡° ͜ʖ ͡°) dzięki za linka
@Harry19911: Nie jest dobrym pomysłem robić linkujące się nawzajem usługi.

Jeśli już, miej te dwie usługi, ale utwórz trzecią, która korzysta z obu.

Czyli specjalizuj, a potem komponuj (zamiast robić skomplikowaną sieć zależnych powiązań – niech będą zawsze jednokierunkowe).
@Harry19911: Wysłanie ticketa i odpowiedź na niego to dwa różne przypadki użycia (use case), a więc dwie różne pary kontroler-serwis. To, że korzystają z tych samych encji nie ma znaczenia.
1. TicketManagerController(TicketManager(Ticket, Mail))
2. TicketCreatorController(TicketCreator(Ticket, Mail))
Jeśli za pomocą dodatkowej warstwy chcesz zrobić z encji obiekt biznesowy to serwis stoi jeszcze wyżej.
@Harry19911: Świetna prezentacja na temat DDD (domain driven development):

https://www.youtube.com/watch?v=ajhqScWECMo

Powyższe jest dosyć zaawansowane, ale polecam obejrzeć – pewnie w przyszłości do tego wrócisz.

Tymczasowo jednak, domyślam się, że chcesz to napisać jako SOA (service oriented architecture), więc kilka praktycznych porad:

* usługi rób mocno wyspecjalizowane – dosłownie jedna metoda publiczna, która coś robi i konstruktor dla zebrania zależności
* z powyższego wynika też nazewnictwo – usługa
@MacDada: dobra prezentacja. Niedawno jak szukałem jakichś bardziej profesjonalnych tutków o Symfony to znalazłem tylko best practices Symfony i zasady typu SOLID itd. A tutaj koleś dobrze pokazał jak się to powinno robić.

Problemy tego typu co we wpisie to miałem nie raz w innym, rozbudowanym systemie. Myślę że teraz mogę tam to eventami naprawić.

@fmfd: chodzi o to żeby nie "zaklejać taśmą" tylko zrobić dobrze ( ͡° ͜