Eseménykezelés PHPben egy vagy több függvény?
Halihó!
Gondolkodom egy eseménykezeléshez hasonló struktúra létrehozásán PHP alapon. Nagy kérdés előtt állok. Az első lehetőség, hogy a feliratkozott ojjektuokban legyen egy függvény, ami paraméterként kapja az esemény tipusát, a másodikban sok függvény kezelné a nevének megfelelő funkciót. Eddi gígy okoskodtam:
Egy fv
- string összehasonlításnál nehezen jövök rá, ha elgépeltem az esemény nevét, sok fogcsikorgatás
- a különböző eseményeket 99%-ban úgy is egy-egy funkciónak dobom át, fölöslegesen kell egy switch (vagy select, vagy akárhogy is hívják) minden egyes hallgatózó osztályban
Több fv
reflexióval
- a reflexiós api-t kell használni (method_exists) egy síma IF helyett (pl ha egy eseménytipusra nem kíváncsi a figyelő)
- call_user_method -dal kell hívni az egyes függvényeket (kérdéses overhead)
- még mindig nem derül ki, ha elgépeltem az esemény (vagy függvény) nevét valahol
interfésszel
- minden eseményküldönek saját interface tipussal kell rendelkeznie a hallgatózó objektumok számára
+ megoldódik az elgépelés problémája
- üres funkciókat létre kell hozni a nem figyelt eseményeknek is (nomeg ennek az overhead-je)
Nagyjából eddig jutottam, most azon tűnődök egyáltalán érdemes-e nekivágni ;)
■ Gondolkodom egy eseménykezeléshez hasonló struktúra létrehozásán PHP alapon. Nagy kérdés előtt állok. Az első lehetőség, hogy a feliratkozott ojjektuokban legyen egy függvény, ami paraméterként kapja az esemény tipusát, a másodikban sok függvény kezelné a nevének megfelelő funkciót. Eddi gígy okoskodtam:
Egy fv
- string összehasonlításnál nehezen jövök rá, ha elgépeltem az esemény nevét, sok fogcsikorgatás
- a különböző eseményeket 99%-ban úgy is egy-egy funkciónak dobom át, fölöslegesen kell egy switch (vagy select, vagy akárhogy is hívják) minden egyes hallgatózó osztályban
Több fv
reflexióval
- a reflexiós api-t kell használni (method_exists) egy síma IF helyett (pl ha egy eseménytipusra nem kíváncsi a figyelő)
- call_user_method -dal kell hívni az egyes függvényeket (kérdéses overhead)
- még mindig nem derül ki, ha elgépeltem az esemény (vagy függvény) nevét valahol
interfésszel
- minden eseményküldönek saját interface tipussal kell rendelkeznie a hallgatózó objektumok számára
+ megoldódik az elgépelés problémája
- üres funkciókat létre kell hozni a nem figyelt eseményeknek is (nomeg ennek az overhead-je)
Nagyjából eddig jutottam, most azon tűnődök egyáltalán érdemes-e nekivágni ;)
WinAPI
A jó megoldást én sem tudom (de érdekel!)
Csak egy kis adalék: a Windowsban pl. az események számkódok, az API hívásokban pedig a megfelelő konstansokkal szokás őket helyettesíteni.
Ezt Te is meg tudod csinálni, így az általad sokszor emlegetett string összehasonlítás problémája megoldódott, az elgépelést a fordító kiköpi.
Norbi
Oh, a windows
A konstansokkal a fő probléma, hogy próbálom amennyire lehet egységbe zárni a dolgokat, ezért nem szeretnék globális konstansokat definiálni pl: USER_CREATED, USER_PASSCHANGED, USER_PASSRESET ... De köszönöm az észrevételt, valóban Notice-olna a PHP ha definiálatlan konstanst használok.
Javában persze lehetne static final-lal definiálni gyönyörűszépen, de ha a java és php különbségeire gondolok ismét nehéz megőrizni a hideg vért :)
MVC
Szerintem neked egy egyszerű MVC pattern megvalósítására lenne szükséged:
Egy egyszerű MVC megvalósítása php5-ben
A lényeg, hogyha az URL így néz ki: http://foo.com/controller/action
Akkor a "Controller" objektum "action" metódusa fog lefutni. A futtatást a "Router" végzi, de sok egyéb objektum is elkellhet.
Megnéztem
Amúgy vicces a cikk, olyan "kisgyerek a cukorkásboltban" fíling, látszik ahogy rajong a tag ezekért a fícsörökért :)
symfony 1.1
Amit téged érdekel az a lib/event könyvtárban van. Az sfEventDispatcher-nél regisztrálják magukat a figyelők bizonyos esemény(ek)re, az esemény maga pedig egy sfEvent példány. (itt egy példát is találsz a működéséről)
sfEventDispatcher.class.php
Nem objektum orientált?
Itt az esemény neve egy string (amit persze továbbra is elgépelhetsz :), de ez bármikor megeshet). Az event dispatcher-nél callback-et lehet regisztrálni, ergo akár osztály- vagy objektum metódust is (remélem nem a példámból indultál ki, az direkt csak egy egyszerű függvény). Mellesleg a témafelvetésedben call_user_method()-ot emlegetsz, ehhez képest szerinted a call_user_func() problémás.
Ha bekövetkezik egy esemény, akkor a dispatcher az adott esemény névre regisztrált hallgatókat szépen végighívogatja egy paraméterrel, ami maga az esemény (sfEvent példány). Ettől kezdve nem akadályoz meg semmi, hogy kiterjeszd az esemény osztályt és a figyelővel csak bizonyos típusú eseményeket dolgozz fel.
OO
A call_user_func-cal történt hívás után nem egy objektum tagfügvénye kerül meghívásra, hanem csak egy függvény, ami ugyebár alacsonyabb rendű szervezhetőséget biztosít (nincsenek adattagok). Egy objektumot inicializálhatok a megfelelő adatokkal, majd regisztrálom. Az események kezelésekor ő felhasználhatja az emltett adatokat (adattagok). Ezzel szemben egy funkció nem rendelkezik saját adatokkal.
Így elméletben lehet, hogy egy kicsit szraz, de remélem a lényeg átjön :)
Egyre jobban érdekel
- egy függvény:
Ha félreértettem valamit szólj. Egyre jobban érdekel mit tudunk ebből kihozni.
Ott a pont
observer pattern
Szóval lehet egy alap Observable interfészed. A különböző típusokhoz készítesz egy absztrakt osztályt, és a konkrét figyelőket ezekből származtatod. Az abstract osztályon már meg tudod határozni, hogy csak adott típusú paramétert fogadjon el az attach metódusa, míg az Observable interfész még csak egy általános Observer típust/interfészt ír elő.
Érdemes még megnézned az SPL ilyen írányú támogatását is: SplObserver, SplSubject. Illetve érdemes lehet megnézni pár keretrendszert, hogy hol milyen megoldást választanak. Egy érett rendszerben jó eséllyel egy kiforrott és kényelmesen használható megoldást lehet találni.
Üdv,
Felhő