PHP OOP tapasztalatok, sebesség, átláthatóság
2008-12-01T19:25:32+01:00
2009-02-03T13:04:28+01:00
2022-07-25T17:16:16+02:00
  • Novát valahogy mindig leoltják
    Mutasd a teljes hozzászólást!
  • Én a cakephpt használom és nagyon tudom ajánlani. Már az első héten meg fogod kérdezni hogy eddig miért nem ezt használtam?.

    Eddig miert nem ezt hasznaltad?
    Mutasd a teljes hozzászólást!
  • CodeIgnitert vagy Kohana-t is érdemes megnézni szvsz
    Mutasd a teljes hozzászólást!
  • De ha már OOP, akkor meg kell nézni a cakephp-t, vagy a simfonyt. Hogy melyik a jobb, azt nem tudom, de mindkettőt érdemes megtekinteni. Még ha nem is használod, sok mindent elleshetsz, ami később még jól jöhet. És legalább megismered az MVC modellt is.
    Én a cakephpt használom és nagyon tudom ajánlani. Már az első héten meg fogod kérdezni hogy
    eddig miért nem ezt használtam?
    . Persze pár hétre rá megkapod erre is a választ . Ennek ellenére szvsz jobb vele, mint nélküle.


    Mutasd a teljes hozzászólást!
  • Keretrendszerből jelenleg csak Smartyt használok, de az csak kicsit vág témába . Gondolkoztam a Pear-en, ott sok okosság van, de a szerver nem saját, és nem lehet telepíteni.
    Mutasd a teljes hozzászólást!
  • Egyetértek Crystallal, valami ilyen megközelítést alkalmazok én is, eddig megfelelt. Alább leírtan, hogy container objektumokat használok, amik minden olyan műveletet is végeznek, ami több adott típusú objektumra értelmezett. Tehát a Message obj. egy üzenetet tud törölni, a MessageContainer különböző kritériumok alapján többet. A topic pedig minden "csatolt" objektumot is töröl. Ha egyenként lenne törölve minden típusú objektum (pláne ha az adatbázis-beli páruk is), akkor meglehetősen erőforrás-igényes lenne.
    Mutasd a teljes hozzászólást!
  • Köszönöm a választ!

    DB dolgoknál én a beépített mysqli classt használom közvetlenül, de az egyéb containereknél lehet nekem is jó lenne iterator felületet írni. Jelenleg ez nálam úgy van, hogy a containerben az összes elem egy tömbben van, és azzal lehet dolgozni, de "egysoros" iteráció nincs.
    Mutasd a teljes hozzászólást!
  • Ha már OOP, akkor érdemes elgondolkodnod egy keretrendszeren is. Mivel még csak messziről piszkálgatod, biztosan sok okos ötletet meríthetsz akkor is, ha végleg nem is térsz át.
    Mutasd a teljes hozzászólást!
  • 4.

    leginkább $forum->del();
    a del() metódus pedig törli a benne levő témákat, a témák pedig a bennük levő üzeneteket.

    Azért, mert az alkalmazás szempontjából az a lényeg, hogy törölni akarod a fórumot. Ez a fórum felelőssége, neki kell a részletekkel foglalkozni.
    Mutasd a teljes hozzászólást!
  • Mi a leg elegánsabb megoldás az objektumok közti kommunikációra OOP szemlélet szerint?
    Pl. van egy forumom, ami áll Forum, Topic, meg Message osztályokból. Mivel lehet tötölni üzeneteket is, egész témákat is és teljes forumokat is, így mindegyiknek van mondjuk del metódusa.

    Most ha törlök egy topicot, törölni kell annak üzeneteit is, stb.
    Ilyen helyzetekben mi a javasolt megoldás?

    1. Forum törlésekor átadom a többi objektumot is?
    $Forum->del(&$forumList, &$Topic, &$Message)
    a metóduson belül meg meghívódik a Topic del metódusa, átadva neki a Message objektumot, és majd az meghívja a Message del metódusát?

    2. Nem adom át az objektumokat, hanem azok a metódusokon belül lesznek példányosítva?

    3. A controllerből hívom meg külön-külön a metódusokat?
    $Forum->del()
    $Topic->del()
    $Message->del()

    4. Valami egészen más megközelítés?
    Mutasd a teljes hozzászólást!
  • Nem, az angollal semmi problémám nincs. A baj inkább mint írtam, hogy pár dolog nem világos, és ezért kérdeztem rá a dologra. A linket pedig köszönöm, ha lesz egy kis időm bele is ásom magam.
    Mutasd a teljes hozzászólást!
  • Hát nekem úgy tűnik, hogy az angollal is hadilábon állsz. A prepare előkészítés a statement objektumokhoz kapcsolódik, szóval jobb esetben SQLStatement-et hozol létre vele. A statement lényege, hogy létrehozol egy sablont, amibe aztán a megfelelő helyekre változókat helyettesítesz be. Aztán csak ezután küldöd el a kérést.
    Ezek után nem hiszem, hogy tudnék segíteni a MySQL osztályoddal kapcsolatban, mert elég kuszának néz így ki.


    Az egésznek az alapja: mysqli. A MySQL osztályod egy kapcsolatot reprezentál, tehát kapcsolatonként elég egy ilyen osztályt példányosítani. Egy kapcsolat nyilván több kérést is indíthat egymás után.
    Mutasd a teljes hozzászólást!
  • Sziasztok!
    Egy kis rámutatást szeretnék kérni a dolgokra, mert most nagy a káosz nálam.
    Tehát van egy MySQL osztályom ezzel kapcsolódok az adatbázishoz valamint a prepare() tagfüggvénnyel létrehozok egy MySQLResult objektumot, amely feldolgozza és visszaadja az adatokat éppen ahogy szükség van rá. Ez eddig szépen működne is, csak akkor akadtam el mikor épp pl.: UserLogin osztályt következett volna. Ehhez ugye kell mysql, tehát használom a MySQL osztályomat. Itt nem világos a dolog, hogy minden egyes lekérdezésnél nekem újra és újra létre kell hoznom egy MySQL objektumot:
    $mysql = new MySQL('localhost', 'nev', 'jelszo', 'adatb'); $mysql->prepare('SELECT * FROM user')->fetch_array(); //eredmény
    Mert ez nekem nem tűnik egyáltalán célravezetőnek. Biztos nem így szokás csinálni, tehát a kérdésem az lenne milyen módon lehet ezt elegánsan megoldani?

    Előre is köszönöm!
    Mutasd a teljes hozzászólást!
  • Öhh, ha az előzőben nem világos
    Van egy Statement class, ami container, és akkor jön létre, amikor meghívom a prepare függvényt, aztán van egy Result class, ami pedig a result objectre húz egy iterator felületet, valamennyire az is containernek tekinthető.
    Mutasd a teljes hozzászólást!
  • 2) Jó gyakorlat-e "konténer" classokat létrehozni, amik több azonos típusú (a konténerhez tartozó, pl. UserContainer-User) objektumot tartalmaznak? Illetve ezekben van az összes metódus, ami több adott típusú objektumot dolgoz fel (a hozzá tartozó, "tárolandó" objektumban pedig minden olyan metódus, ami egy db adott típusú objektummal végez műveleteket).

    Ez olyan ízlések és pofonok téma. Én most éppen javascriptben a jquerys megközelítést használom a dom kezelésére, szóval gyakorlatilag a sima node classem (a node, amiket containerbe szedsz), az a namespaceben rejtve marad, és csak a container class public. Nem azt mondom, hogy ez a legjobb megoldás, de a végeredménye nagyon jól használható lett.

    Ami miatt megéri phpben container classeket használni az a chainelés sztem.
    Pl:
    foreach(Database::user('root')->prepare('insert into table (a,b,c) values (:a,:b,:c)')->setData(array(a=>1,b=>2,c=>3)->request() as $k => $v) { ... }
    tömörebb, mint
    $user=Database::user('root'); $stmt=$user->prepare('insert into table (a,b,c) values (:a,:b,:c)'); $stmt->setData(array(a=>1,b=>2,c=>3); $result=$stmt->request(); foreach($result as $k => $v) { ... }
    Persze ennek is van hátránya, a hibakezelést nehezebb így megoldani.
    Mutasd a teljes hozzászólást!
  • Singletont kipróbáltam, eddig jónak tűnik, bár elég sok helyen azt írták hogy tök fölösleges használni, meg hogy vigye el az ördög :)

    Így jobban belegondolva, ez az egész OOP mintha egy nagy vallás lenne. Legalábbis elég sok különböző vélemény van róla. :)
    Mutasd a teljes hozzászólást!
  • Nézz körül a statikus elemeknél, illetve a singleton is szóba jöhet.
    Mutasd a teljes hozzászólást!
  • 1, köszi , ez eszembe sem jutott :)

    2, inkább kerülném mindig az átadást, de ha így kell, akkor így lesz :)
    Mutasd a teljes hozzászólást!
  • 1 referencia
    $user= &$_SESSION......

    2 (nem tudom mennyire elegáns de) referencia
    fv-ben átadod a $user class-t
    így a fv hívások így fognak kinézni: $class1->class2->method(param)
    Mutasd a teljes hozzászólást!
  • Sziasztok,
    Most ismerkedem a PHP OO programozásával, és azzal kapcoslatban lenne néhány kérdésem, illetve hogy ti hogy oldanátok meg. Gondolkoztam, hogy feltegyem-e tudástárban a kérdéseket, de azután úgy gondoltam, hogy nem, mivel működnek, csak lehet hogy van rá jobb megoldás, így csak a véleményeteket kérném ki.

    Először is, van egy User classom, ami ugye tárolja a belépett felhasználó adatait, ezt ugye sessionnal kéne megoldani, de a neten csak ezt a megoldást találtam, és eléggé nem szakszerű megoldásnak tűnik nekem:


    if ( isset($_SESSION["user"]) ) $user = $_SESSION["user"]; else{ $user = new User(array("todo" => "createguest")); $_SESSION["user"] = $user; };

    A másik, meg hogy, egy másik classbol elérjem pl. az user class functionjait. Most ezt úgy oldom meg, hogy ahol használnom kell, irok egy global $user; -t , és akkor már simán engedi.

    Ezekre esetleg van valami szebb megoldás?
    Mutasd a teljes hozzászólást!
  • Nagyon szépen köszönöm részletes válaszodat!

    1) Ez nagyon jó, gondolom így kisebb lesz a program memóriafoglalása is (mivel nem kell létrehozni egy objektumot az adott classból).

    2) Átláthatóbb lett a kód, eddig bevált ez a módszer. Megpróbálok arra vigyázni, hogy ne keverjem az általános megoldásokat a script-specifikusakkal, így a konténer egy általánosan használható objektum marad. Remélhetőleg ez majd a későbbiekben is beválik .

    3) Szerencsére eddig viszonylag átlátható kompozíciói vannak, és kölcsönös függőség nincs, úgyhogy az általad leírt megoldást fogom alkalmazni.

    4) Az xml nagyon elegánsnak tűnik, egyébként a sebessége is megfelelő szerinted? Azt olvastam a PHP 5 xml könyvtára elég jóra sikerült.

    Klasszikus front controllert most már nehézkes lenne alkalmaznom (át kellene írni mindent a weblapomon), így az ilyen dolgokat kevésbé elegáns módon oldom meg, valahogy úgy, ahogy itt van leírva.

    Az ilyen kérdésekre a legnehezebb választ találni, mert általában csak mások kódjának tanulmányozásával lehet. Olyanból meg ritkán találni olyat, ami ténylegesen helyes szemléletet követ, megfelelően összetett az ilyen kérdések megválaszolásához, de nem túl bonyolult ahhoz, hogy viszonylag kezdő fejjel is meg lehessen érteni... Szóval nagyon sokat segítettél, köszönöm!
    Mutasd a teljes hozzászólást!
  • 1. lehet éppen singletonozni ha akarsz de ez szerintem az utility class tipikus esete magyarul statikusan hívd meg az osztály metódusait.

    2. hát ha a konténer osztályt csak arra akarod használni hogy "ami több adott típusú objektumot dolgozzon fel" akkor ahhoz nem hiszem hogy érdemes külön osztály, de ahogy gondolod (ha te úgy látod hogy így átláthatóbbá tehető a kód akkor nyugodtan).

    3. a függőségek elkerülhetetlenek, ha nem túl bonyolult a kompozíció-hierarchia akkor érdemes olyan konstruktort írni amelynek kötelezően meg kell adni a függőséget. A dolog persze nem működik, mikor két osztály kölcsönös függőségben van egymással (valamelyiket mindenképp példányosítani kell akkor mikor a másik még nem létezik, tehát itt az elsőként létrehozott objektumnak konstruktorban nem lehet megadni a függőséget)

    4. hát lehetni lehet de inkább használj ini vagy xml konfig fájlt, sokkal elegánsabb.

    Más: használj front controllert, megoldja a "minden fájl elején valamit megcsinálni" problémát.
    Mutasd a teljes hozzászólást!
  • Miután már lényegében hetek óta a címben szereplő témával foglalkozom, lenne néhány olyan kérdésem a tapasztaltabbakhoz, amire sehogy sem találtam választ.

    1) Jó ötlet olyan függvényeket, amik egy "témához" tartoznak (pl. string-kezelő függvények), egy singleton class-ba csomagolni, majd minden script elején létrehozni (mivel gyakorlatilag mindegyik scriptben használva van) és a többi classban kompozícióval használni a metódusokat (tehát a class már létező darabját - mert minden oldal elején létrehozzuk - minden további nélkül használni)?

    2) Jó gyakorlat-e "konténer" classokat létrehozni, amik több azonos típusú (a konténerhez tartozó, pl. UserContainer-User) objektumot tartalmaznak? Illetve ezekben van az összes metódus, ami több adott típusú objektumot dolgoz fel (a hozzá tartozó, "tárolandó" objektumban pedig minden olyan metódus, ami egy db adott típusú objektummal végez műveleteket).

    3) Szintén, jó gyakorlat-e egy classban kompozícióval egy másik classból létrehozott objektumot használni úgy, hogy feltételezzük, olyan objektum létezik (mivel minden scriptben szükség van rá). Tehát így bizonyos classoknak van elsőre nem látható "függősége", csak önmagukban nem lehet őket használni. Hasonló az 1-eshez, de itt a "használó" classban lévő megoldásra vonatkozik a kérdés, míg az 1-esnél a "használt" classra.

    4) Jó gyakorlat-e a saját classok által használt közös konfigurációs változókat (vagy éppen konstansokat, pl. hány bejegyzés legyen egy lapon) egy sima php fájlban tárolni listaszerűen, azt az őt használó script elején include-olni, majd az összes alatta levő objektumból a változókat "csak úgy" használni (esetleg láthatósági probléma esetén a global kulcsszóval). Itt megint "függősége" lesz egy-egy classnak (vagy azok egy-egy metódusának). Vagy az adatokat inkább egy singleton class tulajdonságaiban kellene tárolni, majd a 3-as módon kompozícióban használni?

    Gyanítom, hogy az utolsó kettő nem éppen így a legjobb...

    Nagyon megköszönnék akár igen/nem-es válaszokat (ez a 4-es esetén a kérdés első részére vonatkozik ), nem esetén esetleg egy kulcsszóval, amin elindulhatok .
    Mutasd a teljes hozzászólást!
  • Köszönöm a linket, eddig egy kicsit egyszerűbben ismertem a réteges megközelítést .
    Mutasd a teljes hozzászólást!
  • Na találtam egy linket, ami bár elég régi, de szépen ábrázolja a dolgot :)

    Content moved to Ee817639

    Annyi a hiba benne, hogy a Business Enities-t a 3 réteg mellé kellett volna rajzolniuk.
    Mutasd a teljes hozzászólást!
  • Akkor félreértettem, késő (vagyis inkább korán van. Furcsának is tűnt .
    Mutasd a teljes hozzászólást!
  • Ha külön classokban van az adatbázis-elérés, és az üzleti logika, akkor futhatnak külön gépeken? És ez PHP-re is áll? Csak mert nagyon nehezem tudom elképzelni, hogy az interpreter lefordítja az egyik classt, az meghívja a másikat, és a másik gépen futó másik class meg visszaad egy eredményt...


    Hajjaj :)

    1. Nem értek a php-hoz nem tudom milyen lehetőségek vannak.

    2. Rossz a megközelítés, nem azt mondtam, hogy ha külön osztályaid vannak, akkor azt az interpreter kezelni tudja.

    3. Nem a dataaccess és a bl különrakása volt jelenleg kiemelve, de azokat is érdemes külön projektben megvalósítani (pl ha más adatbázisra térsz át, egyszerűen lecseréled, egy másikra), persze az is tuti, ha van vmi általános adatelérő komponensed.

    4. A lényeg, hogy ha külön osztály az üzleti entitásod, és külön osztály a bl-ed, akkor könyebben tudsz egy homlokzatot rárántani a bl-edre, így abból egy szolgáltatást készítve, és hosztolva. A szolgáltatás üzleti entitásokat vár, ad vissza, a kliens meg szintén ugyanolyan típusú üzleti entitásokat ad át, kér el. Ennyi.

    A kliens, és a szolgáltatás közötti kommunikáció is egy külön téma, sok lehetőség van a különböző futtatási környezeteknél, spec a php-sokat nem ismerem. Amire céleoztam, hogy célszerű úgy tervezni, hogy ha későbbiek során skálázni szeretnél (pl külön gépen a webapp, küölön gépen a szolgáltatás), ne akkor kelljen áttúrni a kódot.
    Mutasd a teljes hozzászólást!

  • Egy szó mint száz, ha egy osztályban van az entitás, és a bl/dataaccess metódusod, akkor nem lesz olyan egyszerű megoldani, hogy pl az adatelérést, bl-t külön gépe(ke)n futtasd a webapptól.


    Engem ez véletlenül se érint, csak elméleti szinten kérdezem. Ha külön classokban van az adatbázis-elérés, és az üzleti logika, akkor futhatnak külön gépeken? És ez PHP-re is áll? Csak mert nagyon nehezem tudom elképzelni, hogy az interpreter lefordítja az egyik classt, az meghívja a másikat, és a másik gépen futó másik class meg visszaad egy eredményt...
    Mutasd a teljes hozzászólást!
  • Talán valami DNS-cache hiba :/.

    De itt vannak a grafikonok.

    És ez volt hozzá a leírás:

    Conditions

    CPU: 64-bit AMD Sempron 3000+ @ 1 GHz
    OS: Gentoo Linux (x86-64) w/kernel: 2.6.22-gentoo-r6
    RAM: 1 GB total

    Scripting Language Versions:

    PHP: 5.2.5-pl0-gentoo w/suhosin
    Perl: 5.8.8
    Python: 2.5.1
    Ruby: 1.8.6 (2007-12-03 patchlevel 113)

    All tests were run consecutively, and thus had approximately the same amount of memory and CPU time available to them.

    Method

    A bash script was used to automate testing and record results. A perl script was used to average the run times and give a result.

    Test Programs

    Two test programs were measured:

    Hello - Prints "Hello World" to stdout.
    Inc - Increments a variable, starting at 0.

    Each program does one-million iterations, and is run ten consecutive times. It's also worthwhile to note that for these type of benchmarks use of OOP or a function would be impractical.

    The test programs, shell script, perl script, and an Open Office spreadsheet can be downloaded here.
    Mutasd a teljes hozzászólást!
  • Régebben talán az volt az elfogadott tézis, hogy minden egyes táblához legeneráltak egy saját típusú class-t, óriási felesleges kódbázist létrehozva, de ma már az látszik, hogy a gyorsabb és rugalmasabb munka érdekében ezek a hibernate jellegű adatszolgáltatók előtérbe fognak kerülni.


    Én nem php-zok, de jelenleg is ez a tézis enterprise architektúráknál, mármint, hogy külön osztályokban tároljuk az üzleti entitásokat, mégpedig azért, mert sokszor ugyanazt az assembly-t használja a kliens, és a szolgáltatás is.

    Itt most arra kell gondolni, hogy a kliens, tegyük fel egy webalkalmazás ami főként megjelenítésére szolgál, az adatokat egy szolgáltatástól szedi le, ami nem biztos, hogy egy process-ben van a webalkalmazással (tehát nem direkt referencia, vagy "include").

    És azért az nem szép, ha a kliens elérhet olyan metódusokat, ami egy adatbázis lekérdezést futtat, ami így hibára is futna :)

    Egy szó mint száz, ha egy osztályban van az entitás, és a bl/dataaccess metódusod, akkor nem lesz olyan egyszerű megoldani, hogy pl az adatelérést, bl-t külön gépe(ke)n futtasd a webapptól.

    Persze valószínűleg jelen esetben nem szükséges ez a módszer, de én szeretem így tervezni alapból az architektúrát.
    Mutasd a teljes hozzászólást!
abcd