Komentáře k článku

Doctrine 2: události

V předchozích dílech seriálu jsme si představili základní možnosti Doctrine 2. S nimi dokážete zajistit jednoduché mapování objektů na databázi. Dnes a příště se podíváme na první z pokročilejších témat, a to na životní cyklus entity, události, listenery a subscribery.

Zpět na článek

14 komentářů k článku Doctrine 2: události:

  1. Ghost

    Re: Doctrine 2: události

    Nevim, z javy jsem na anotace zvykly, ale jejich pouziti v php se mi prici – zejmena kvuli nepodpore v IDE.

    Udalosti (triggery) jsou samozrejme potreba, ale zrovna 2x se mi nelibi jejich pouziti v Doctrine2. Osobne pouzivam zpusob, kdy mam vytvorenu hlavni tridu, ktera implementuje vsechny metody udalosti. Podedena trida si je pak akorat pretizi a dela si svoje.

    Mam tak v kodu vetsi prehled a zarucene stejne nazvy pro jednotlive udalosti.

    Taky mohli dat prefixy before a after, nez pre a post …

    „Jedná se o běžnou třídu, která nemusí ani nic dědit či implementovat. Měla by mít ale metody pojmenované podle názvů událostí, na které ji chceme navěsit.“
    Mela by mit … nemam rad tento pristup, uprednostnuju interface + pripadne adapter …

    1. drobna chyba

      Re: Doctrine 2: události

      array(Events::per­Persist, Events::preRemove),
      melo by byt
      array(Events::pre­Persist, Events::preRemove),

    2. Jan TichýAutor příspěvku

      Re: Doctrine 2: události

      Osobne pouzivam zpusob, kdy mam vytvorenu hlavni tridu, ktera implementuje vsechny metody udalosti. Podedena trida si je pak akorat pretizi a dela si svoje.

      Tedy zneužívání dědičnosti k něčemu, k čemu by se dědičnost vůbec používat neměla?

      Mam tak … zarucene stejne nazvy pro jednotlive udalosti.

      Soulasím s tím, že tohle není v Doctrine 2 úplně čisté a že by rozhraní jednotlivých listenerů mělo být vyžadováno jako implementace nějakých daných interfaces. Zkusím v tomto smyslu poslat vývojářům návrh do diskuze.

      Mela by mit … nemam rad tento pristup, uprednostnuju interface + pripadne adapter …

      Jak jsem už napsal výše, s tím souhlasím a také se mi to nelíbí.

      1. drevolution

        Re: Doctrine 2: události

        U toho sjednocování názvu listenerů bych si nebyl tak jistý. Znamenalo by to, že by entita měla metody jako prePersist či preUpdate, případně nějaké variace na toto téma? Takováhle metoda by v entitě přeci neměla strašit. Z mého pohledu to do entit zatahává části náležící persistanční vrstvě.

        Čistější se mi zdá aktuální přístup, tedy že se naslouchání řídí „značkováním“ metod. Ano, nepříjemné je to, že má pak člověk bordel v tom, jaká metoda je volána event handlerem (zde by se opravdu hodila podpora ze strany IDE), ale z akademického pohledu mi to přijde smysluplnější.

      2. Ghost

        Re: Doctrine 2: události

        „Tedy zneužívání dědičnosti k něčemu, k čemu by se dědičnost vůbec používat neměla?“

        Smim se zeptat, proc by se takto nemela pouzivat dedicnost, resp. cim ji zneuzivam? Jaky zpusob je tedy ten spravny?

        Osobne mam takovyto pristup zazity a nevidim na nem nic spatneho.

        Nelibi se mi totiz tento pristup:
        $article = new Article;
        $em->persist($article);

        je mi milejsi pouzivat neco takoveho:
        $article->persist();

        Mozna k tomu pristupuju spatne, ale takto mi entita „predstavuje i ten persistentni objekt“ – nekde uvnitr je schovany EM.

        1. Jan TichýAutor příspěvku

          Re: Doctrine 2: události

          Aha, tak to se dopouštíte dokonce dvou chyb zároveň ;). I když slovo „chyba“ zde nechápejte nějak tvrdě jako něco, co je vysloveně špatně, spíš něco, co se v teorii i praxi neukázalo být jako ta nejlepší cesta, ale spíš jako cesta, po které se jde docela dlouho celkem pohodlně, ale na které pak dříve či později strašlivě narazíte a vymlátíte si všechny zuby.

          Prvním bodem je design pattern nazývaný ActiveRecord, tedy to, co Vy označujete jako $article->persist(). Oproti tomu stojí jiné univerzálnější a systémově správnější přístupy, například Data Mapper. Pro více informací viz google, byly o tom napsány stohy pojednání. Z vlastní zahrádky například úvod u článku Doctrine 2: načítání, ukládání a mazání nebo lehce zavádějící, lehce pomýlený a zastaralý, ale v tomto smyslu stále užitečný článek Pět vrstev modelu.

          Druhým bodem je pak dědičnost v OOP. Ta je určena výhradně ke specializaci obecnější třídy – ovšem ve smyslu věcné podstaty třídy, její domény, nikoliv obecné funkčnosti. Zneužívání dědičnosti pro znovupoužitelnost obecných funkcí nesouvisejících s doménou třídy je bad practice, vede k chybným programátorským postupům a naprosto vadným návrhům aplikace. Oproti tomu jako best practice stojí tzv. kompozice, tedy skládání požadované funkčnosti z více různých samostatných tříd, jako je tomu například právě zde v případě samostatných registrovaných listenerů. Opět viz google a hromada dalších zdrojů, například nějaká literatura o návrhových vzorech.

          1. Ghost

            Re: Doctrine 2: události

            Diky za reakci.
            ad. 1.
            jasne, zatim jsem nenarazil, takze mi takovyto zpusob vyhovoval
            ad. 2.
            ActiveRecord … no, jak se to vezme … V pozadi se porad pouziva nejaky mapper, ktery se o entity stara. Metody entit (napr. persist()) jsou jen prostrednici, zajistujici komunikaci s mapperem. Zmena mapperu je porad mozna. V tomto pripade vidim kolizi hlavne v pojmu entita – kdy neni jenom schranka ale uz neco i dela, resp zprostredkovava.

            Hlavni duvod proc jsem zvolil tento pristup je predavani instance entity manageru do jinych trid (zejmena do kontroleru), kdy neni vhodne (a ani nemusi byt vzdy potreba) jej predavat v konstruktoru ci v inicializacni metodou.
            Dalsi moznost by bylo ziskani EM z nejakeho singletonu – ale toto reseni se mi taky nelibi.

            Jaky postup byste mi tady doporucil?

            ad.3
            Jasne, kompozice je ok, ale ne vzdy a vsude jsem ji schopen nasadit. Registrovat samostatne vlastni listenery je samozrejme v poradku. Ja narazel na definici jednotlivych udalosti.

            Pouzivam udalosti ve smyslu trigeru, takze ocekavam stejne chovani v pripade jakekoliv manipulace s entitou, kdykoliv a kdekoliv. Takze v tomto pripade mi dedicnost nepripada jako vylozene spatne reseni.

            Nejpis skoncime diskuzi o tom co vsechno ma umet a co ma obsahovat entita a jak se na ni vlastne divat. Jestli z pohledu domeny ci z pohledu perzistentniho prvku (tak se na ni divam ja a vidim to tedy jako vhodny pristup). Z pohledu domeny a tedy vyznamu objektu to vidim taky jinak.

            Diky za komentar.

            1. Jan TichýAutor příspěvku

              Re: Doctrine 2: události

              Hlavni duvod proc jsem zvolil tento pristup je predavani instance entity manageru do jinych trid (zejmena do kontroleru), kdy neni vhodne (a ani nemusi byt vzdy potreba) jej predavat v konstruktoru ci v inicializacni metodou. Dalsi moznost by bylo ziskani EM z nejakeho singletonu – ale toto reseni se mi taky nelibi. Jaky postup byste mi tady doporucil?

              Podle mě nejlepším řešením na tohle je nějaké pokročilé DI/IOC/Service­Locator/Contex­t/nazvětesito­jakchcete – do jiných tříd si pak nemusíte nutně předávat přímo instanci EntityManageru, ale jenom ServiceLocator, ze kterého si případně vhodný EntityManager vyžádáte.

              ServiceLocator přitom nemusí (a rozhodně by neměl) být globálním singletonem, měl by být v různých částech a úrovních aplikace předávatelný a modifikovatelný.

              Zároveň v sobě nemusí nutně nést už hotový instancovaný EntityManager, ale například pouze továrničku nebo obecně jiný nápovědný způsob, jak v případě potřeby EntityManager instancovat na vyžádání. To navíc při pokročilé práci s Doctrine 2 stejně budete potřebovat – občas se vám totiž EntityManager uzavře v polovině práce a vy si potřebujete někde uvnitř aplikace najednou otevřít další nový.

    1. Jan TichýAutor příspěvku

      Re: nevypadá to moc hezky

      Když to srovnám s uvedeným odkazem, tak na něm vidím něco jako set_callback(:sa­ve, :before) nebo before_create, v Doctrine 2 pak pro stejný účel vidím něco jako @prePersist. To je vše, jedna jediná anotace snad není žádný maglajz, ne?

Napsat komentář

Tato diskuse je již příliš stará, pravděpodobně již vám nikdo neodpoví. Pokud se chcete na něco zeptat, použijte diskusní server Devel.cz

Zdroj: https://www.zdrojak.cz/?p=3384