DevProTalk

DevProTalk (http://www.devprotalk.com/index.php)
-   PHP (http://www.devprotalk.com/forumdisplay.php?f=9)
-   -   Generator klasa za pristup bazi podataka (http://www.devprotalk.com/showthread.php?t=834)

Ilija Studen 27. 03. 2006. 20:09

Generator klasa za pristup bazi podataka
 
Ovo pitanje se poteglo pre nekog vremena pa da i odgovorim na njega:

Citat:

Originalno napisao BraMom
Pomenuo si da koristiš neki code generator za kreiranje objekata koji rade sa tabelama u bazi.
Verovatno slično radim pod .NET, koristim CodeSmith.

Programiram i u PHP povremeno, pa bih voleo da čujem koje alate koristiš, nisam naleteo na nešto kvalitetno odrađeno za PHP.

Alat koji koristim sam sam napisao i to prilično davno. Kad sam pre nekog vremena mora da pravim jedan PHP4 skript izvukao sam taj stari kod iz arhive i preradio da liči na stvari koje sam u međuvremenu naučio (izvlačenje objekata slično Railsu itd). Na kraju mi se svidelo na šta je sve izašlo pa sam taj novi prepravio da fino radi sa PHP5 i koristi njegove nove mogućnosti.

Stvar funkcioniše prilično jednostavno. Dve abstraktne klase: DataObject (objekat koji predstavlja jedan row) i DataManager (poseduje definiciju tabele i metode za izvlačenje podataka i keširanje). Generator projuri sve tabele u navedenoj bazi i generiše naslednice ovih klasa tako da npr za usera dobiješ:

/base/BaseUser.class.php
/base/BaseUsers.class.php
/User.class.php
/Users.class.php

Bazne klase sadrže opis objekta i njegove metode (npr. accessori za polja, funkcije za izvlačenje podataka itd). Druge dve klase su prazne i u njih možeš da trpaš svoj kod. Kad sledeći put generator bude preletao diraće samo bazne klase, neće i ove koje ti modifikuješ tako da je sinhronizacija tabela i klasa koje im pristupaju jako jednostavna (izvršim jedan skript), a ti ne moraš da se brineš da će doći do nekog gubitka podataka.

Sve manje više liči na ActiveRecord, ali mi se nije svidelo učitavanje podataka o tabelama i redovima u svakom prolazu pa sam napravio generator. Manje više ista stvar jer ti omogućava:

PHP kôd:

$user Users::findById(12);
if(
$user instanceof User) {
  try {
    
$user->setUsername('root');
    
$user->save();
  } catch(
Exception $e) {
    die(
$e->getMessage());
  }
} else {
  throw new 
Exception('Nema korisnika!');


ili jedan lep primer koji ja volim (ranije sam mrzeo paginaciju, sad pravim kakvu god hoćeš za 2 sekunde):

PHP kôd:

// Dodatni uslovi / trenutna stranica / broj itema po stranici
list($items$pagination) = Messages::paginate(array(
  
'conditions' => '`publish_after` > ' db_escape(new DateTime()),
  
'order' => '`publish_after` DESC'
), 110); 

Dobijem poruke koje su podešene da budu objavljene od trenutnog vremena i objekat koji ima sve informacije o paginaciji (koliko ukupno ima stranica, koja je trenutna stranica, da li ima prethodna i naredna itd). Prikaz prilično složene paginacije se svodi na jedan poziv...

Overkill? Za sve što ima preko 5 tabela ne po mom mišljenju. Sa ovim se stvarno radi brže...

BTW: Mana je što je samo persistance layer, nema mogućnost da skonta relacije među objektima... Za sada ;)

degojs 27. 03. 2006. 20:48

Ako ti treba da skonta "relacije" medju tabelama tipa da bi dobio neki tabelarni prikaz podataka na stranici koji povezuje podatke iz vise tabela u bazi onda samo napravi takav pogled u bazi podataka. Koliko mi je poznato MySQL 5 to podrzava.

A svaki pogled je u biti virtuelna tabela. I onda samo izgenerises klasu i za taj pogled. Naravno, podrazumeva se da ne vrsis apdejt koristeci pogled, vec klase za tabele koje su obuhvacene tim view-om.

Naravno da se stedi vreme mnogo. Svako ko je imao priliku da programira dok se jos vrse razgovori o detaljima, zna koliko ovo pomaze. Npr. svake dve nedelje na sastanak, a tamo malo hoce ovo, malo ono, pa se i sama baza menja.

Imas li podrsku za transakcije? :)

Ilija Studen 27. 03. 2006. 21:19

Podrška za transakcije postoji, naravno. Na žalost, MySQL ne podršava ugneždene transakcije pa se za kompleksnije operacije same trensakcije moraju kontrolisati spolja, ručno. Da li neko za rešenje za ovaj problem?

Što se relacija među objektima tiče kad sam rekao da nema podršku za njih mislio sam da ne generiše funkcija tipa Message::getComments() i slično ili Comment::getMessage(). Ovo i kaskadni update / brisanje je nešto što ću definitivno morati uskoro da dodam pošto jako često nalećem na situacije gde odsustvo toga pravi probleme (ili oduzima vreme ili moram da pazim na stvari koje se inače podrazumevaju).

Što se pogleda tiče oni su jedna od stvari koja mi definitivno nedostaje kod MySQL 4.x. Kad 5ica uđe među mase neće biti problem dodati da generator prepozna view i na osnovu njega generiše read only klase...

dinke 27. 03. 2006. 22:27

Mozda da pogledas PEAR::DB_Data_Object, ona radi skoro isto sto i ovaj tvoj kod, dakle, neka vrsta DAO (Data Access Object) patterna.

Nazovi me jos jednim "old school" momkom ovde, ali meni nista od toga nema previse smisla, tj. isuvise komplikacija da bi bilo korisno u jednom normalnoj PHP aplikaciji. Ja vise volim da sam pisem sql (ukljucujuci i join-e, sam bog zna kako se to radi sa ovim cudom :).

Ilija Studen 27. 03. 2006. 23:01

Prosto učitanje, čuvanje, brisanje + keš + par sitnica (lazy load kolone npr) dobiješ gotove. Proizvod je jasno definisan, proširiv API za sve objekte koje čuvaš u bazi podataka.

Poenta ovoga nije da u potpunosti zameni SQL (kao recimo Criteria kod Propela / Torquea) ili nešto slično tome. Poenta je da napraviš granicu između aplikacije i baze (da ne moraš non stop da brineš o njoj) i automatizuje smorne delove.

Kad treba da odradiš neki složeniji upit samo odradiš:

PHP kôd:

return Messages::loadFromResult(db_execute($sql)); 

Cilj je da se poveća produktivnost i olakša rad, ne da ti sistem visi kao kamen oko vrata koji moraš da vučeš.

Izmena: Pogledah DB_DataObject. Zahteva šemu... Pošto znam kakav je smor kad imaš šemu i kompleksan build proces (Propel) pa malo malo treba da rebuilduješ pored klasa i tabele u bazi to sam izbegao. Imaš bazu, odatle generator kupi informacije o klasama i to je to. Problem je što si osuđen samo na informacije koje baza pazi o tabeli, ali u ogromnoj većini slučajeva to je i više nego dovoljno. Po meni ne pruža svu fleksibilnost šema, ali radi posao dovoljno dobro...

BraMom 28. 03. 2006. 16:58

Nisam odmah video da si odgovorio na "poziv". Vec neko vreme se mislim da napisem neki Code Generator za PHP, pa kad sam primetio da koristis nesto slicno, obradovao sam se da postoji dobro gotovo resenje, ono postoji, samo ne znam da li je open source...

Slazem se da je pristup dobar, on naravno ima ogranicenja, ali te nista ne sprecava da iskodiras rucno kad i sta ti treba, jednostavno skracuje onaj dosadni deo da svaki put iznova pises Select, Insert, Update, Delete.

Pristup po kome sad ja radim (C#), nije moj vec nasledjen od iskusnijeg programera, je da se na osnovu tabela u bazi i gotovih templejta (CodeSmith) generisu neke osnovne SP, znaci GetByPrimaryKey, GetList, Update, Insert, bla bla, templejt je dovoljno pametan da prepozna i Foreign keys pa dobijas jos nekoliko SP-a u zavisnosti od relacija izmedju tabela.
Kad kreiram SP onda obicno dopisem jos neku koja mi treba, eventualno neku izmenim...
Onda generisem DAL (opet CodeSmith) komande (prakticno klase) koje primaju parametre za SP izvrsavaju ih (pune dataset ili sta vec treba) i to mu u osnovi dodje to...
Posle toga svu komunikaciju sa bazom radim pomocu tako generisanog DAL-a, tako da na stranicama nema ni pozivanja SP, niti kakvog drugog SQL-a...

degojs 28. 03. 2006. 16:59

Citat:

Nazovi me jos jednim "old school" momkom ovde, ali meni nista od toga nema previse smisla, tj. isuvise komplikacija da bi bilo korisno u jednom normalnoj PHP aplikaciji. Ja vise volim da sam pisem sql (ukljucujuci i join-e, sam bog zna kako se to radi sa ovim cudom :).
Sve je to lepo dinke, ali kad se radi o bazi sa malim brojem tabela, a tabele sa relativno malo polja.

Zamisli nesto malo vece.. pa treba ti 7 dana samo da otkucas sve CRUD funkcije, pa jos testiranje.. ko ce to vreme da ti odobri (= plati)? Ako isti posao ovakvi alati urade za manje od 1 minuta? I ti alati su obicno DOBRO provereni i testirani - gomila ljudi ih koristi, svi vazniji bagovi su odavno uhvaceni.. Iskreno ja da sam ti sef :), ne bih ti dopustio da gubis vreme na ovakve trivijalnosti.

Sto se JOIN-a tice: taj svoj komplikovani SELECT sa 100 JOIN-ova sacuvas u bazi kao VIEW i onda opet koristis ove alate posto je view u biti virtuelna tabela.. gotova prica.

Dakle, ne drzis se ko pijan plota mantre "ne diram SQL" vec kombinujes jedno i drugo za sto efikasnije i jednostavnije resenje..

dinke 28. 03. 2006. 17:46

Citat:

Originalno napisao degojs
Sto se JOIN-a tice: taj svoj komplikovani SELECT sa 100 JOIN-ova sacuvas u bazi kao VIEW i onda opet koristis ove alate posto je view u biti virtuelna tabela.. gotova prica.

Da, super je to, jedino sto view ne postoji u verzijama MySQL-a < 5.x, a takvi su trenutno preovladjujuci. Thanks but not thanks :)

degojs 28. 03. 2006. 17:57

Pa znam, napisao sam to jos u prvoj poruci.

Nije to onda ni old school ni new school, nego - ne moze i tacka jer baza ne podrzava pa nema sta ni da se prica old school i slicno..

Pedja 29. 03. 2006. 10:10

Nije neizvodljivo da se klasi umesto samo imena tabele da ceo sql upit koji ona tretira kao tabelu.


Vreme je GMT +2. Trenutno vreme je 22:35.

Powered by vBulletin® Verzija 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright © DevProTalk. All Rights Reserved.

Mišljenja, saveti, izjave, ponude ili druge informacije ili sadržaji nastali na Sajtu su vlasništvo onoga ko ih je kreirao, a ne DevProTalk.com, tako da ne morate da se oslanjate na njih.
Autori poruka su jedini odgovorni za ovakve sadržaje. DevProTalk.com ne garantuje tačnost, kompletnost ili upotrebnu vrednost informacija, stavova, saveta ili datih izjava. Ne postoje uslovi pod kojima bi mi bili odgovorni za štetu ili gubitak koji je posledica bilo čijeg oslanjanja na nepouzdane informacije, ili bilo kakve informacije nastale kroz komunikaciju između registrovanih članova.
Web sajt može sadržavati linkove na druge web sajtove na Internetu ili neke druge sadržaje. Ne kontrolišemo niti podržavamo te druge web sajtove, niti smo pregledali bilo kakve sadržaje na takvim sajtovima. Mi nećemo biti odgovorni za legalnost, tačnost ili prikladnost bilo kog sadržaja, oglasa, proizvoda, usluga ili informacije lociranim na ili distribuiranih kroz druge web sajtove, niti za bilo kakvu štetu nastalu kao posledica takvih informacija. DevProTalk.com drži i čuva druga prava vlasništva na web sajtu. Web sajt sadrže materijale zaštićene copyright-om, zaštitne znakove i druge informacije o pravu vlasništva ili softver. Članovi mogu poslatu informacije zaštićene pravima vlasništva njihovih nosilaca i ona ostaju zaštićena bez obzira da li su oni koji prenose te informacije to naveli ili ne. Osim informacija koje su u javnom vlasništvu ili za koje dobijete dozvolu, nemate pravo da kopirate, modifikujete ili na bilo koji način menjate, objavljujete, prenosite, distribuirate, izvršavate, prikazujete ili prodajte bilo koju informaciju zaštićenu pravima vlasništva. Slanjem informacija ili sadržaja na bilo koji deo DevProTalk.com, Vi automatski dozvoljavate i predstavljate garanciju da imate pravo da dozvolite DevProTalk.com ili članovima DevProTalk.com bespovratnu, kontinualnu, neograničenu, globalnu dozvolu da koriste, kopiraju, izvršavaju, prikazuju i distribuiraju takve informacije i sadržaje i da iz takvih sadžaja koriste bilo koji deo u bilo koje svrhe, kao i pravo i dozvolu da koriste gore navedene sadržaje. Svi zaštitni znakovi (trademarks), logotipi, oznake usluga, firme ili imena proizvoda koji se pominju na ovom web sajtu su vlasništvo kojim raspolažu njihovi vlasnici.