ugrás a tartalomhoz

Eseménykezelés PHPben egy vagy több függvény?

vbence · 2008. Feb. 8. (P), 14.10
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 ;)
 
1

WinAPI

N0r3i · 2008. Feb. 8. (P), 15.01
Szia!

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
2

Oh, a windows

vbence · 2008. Feb. 8. (P), 15.57
Ajjaj, de nehéz objektívnek maradni, ha ilyen dolgok repkednek, mint a windows API ;)

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 :)
3

MVC

goph-R · 2008. Feb. 8. (P), 18.14
Hi!

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.
5

Megnéztem

vbence · 2008. Feb. 9. (Szo), 10.41
Köszi, elolvastam, de nekem rendszeren belül keletkező események (amik tulajdonképpen nem is események) elosztására kéne egy ideális módszer, a cikkben inkább egy külső wrapper szintet valósít meg.

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 :)
4

symfony 1.1

Sulik Szabolcs · 2008. Feb. 8. (P), 19.48
Nézz szét a symfony 1.1 tájékán (http://svn.symfony-project.com/branches/1.1). Ez a témakör játsza az egyik fő szerepet pont.

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)
6

sfEventDispatcher.class.php

vbence · 2008. Feb. 9. (Szo), 10.46
Megnéztem. Az pozitív, hogy a Cocoáról veszi a példát, az viszont egyáltalán nem, hogy nem objektumorientált (call_user_func). Elég primitív implementáció, persze lehet, hogy ez a helyes megközelítés ha egy frameworköt ír az ember.
7

Nem objektum orientált?

Sulik Szabolcs · 2008. Feb. 9. (Szo), 11.54
Ezt kifejtenéd?

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.
8

OO

vbence · 2008. Feb. 9. (Szo), 12.19
Az esemény azonosításába direkt nem kötöttem bele, ez megoldható a Norbi által említett módszerrel (konstansok). Ami a "nem oo" problémát illeti, az a bajom, hogy egy függvényt regisztrálsz, amihez nincsenek adatok.

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 :)
9

Egyre jobban érdekel

Sulik Szabolcs · 2008. Feb. 9. (Szo), 13.51
A call_user_func() nem egy függvényt, hanem egy callback-et hív meg. A callback pedig lehet
- egy függvény:

function my_func() {}
call_user_func('my_func');
- egy osztály metódus:

class MyObj {
  static function my_func() {}
}
call_user_func(array('MyObj', 'my_func'));
- egy objektum metódus:

class MyObj {
  function my_func() {}
...
}
$my = new MyObj;
$my->setData1(...);
$my->setData2(...);
call_user_func(array($my, 'my_func'));
Szerintem ez pont azt csinálja amit szeretnél.

Ha félreértettem valamit szólj. Egyre jobban érdekel mit tudunk ebből kihozni.
10

Ott a pont

vbence · 2008. Feb. 9. (Szo), 14.24
Valóban... buta fejjel azt hittem, ha van call_user_func és call_user_method, akkor az egyik funkciót hív, a másik metódust. Ledobálhatjátok a "PHP-OOP" cégért az ajtóm fölül ;)
11

observer pattern

Hodicska Gergely · 2008. Feb. 9. (Szo), 17.40
Az observer minta az, amit szeretnél megvalósítani. Ha így rákeresel, akkor biztosan fogsz találni egy csomó infót róla. Számomra a második jellegű megoldás szimpatikusabb, de ez függhet attól is, hogy hányféle megfigyelt típusod lehet. A kezelők így is úgy is mindenféleképpen kell tudjanak a megfigyelt típus sajátosságairól, viszont az nem rossz, hogy a rendszer szól, hogy ha olyan figyelőhöz szeretnéd hozzáadni az objektumodat, amivel nem is tud mit kezdeni.

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ő