Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: ActiveRecord, ORM
Forum PHP.pl > Forum > PHP > Pro
Stron: 1, 2
seaquest
Na początek po reorganizacji forum chcielibyśmy zaproponować wam temat dotyczący mapowania tabel z baz danych na obiekty w PHP.
Sh4dow
czy czegos podobnego nie robi propel ? Bardzo ciekawe rozwiazanie. Niedawno znalazlem i zachwycam sie co jakis czas biggrin.gif Poza łatwością i przyjemnością w pisaniu, nie miałem okazji przetestować wszystkiego pod względem wydajności.

Edit:
Chociaz przy propel'u to by sie przydalo narzedzie do tworzenia tablic w XML'u. Coś podobnego w stylu tworzenia tablic w phpMyAdmin. Bo na większą skale jest to kosmar tak pisac biggrin.gif
athabus
Moje doświadczenia z klasami tego typu są dość małe. Zastanawia mnie jednak kwestia wydajności. Dla przykładu ZF ma klasę Zend_Db_Table, która jest implementacja Active Record. Zauważyłem, że już przy inicjacji takiej klasy wykonywane jest jedno dodatkowe zapytanie -> w tym przypadku Describe Table. Czyli np, aby odczytać wiersz o id=5 muszę wykonać 2 zapytania - 1 opisujące strukturę tabeli, drugie odczytujące wiersz. Powiem szczerze, że trochę mnie to zniechęca do tego rozwiązania - stosuje je tylko w panelu administracyjnym, gdzie mogę sobie pozwolić na wykonywanie dodatkowych zapytań - na stronach, które są "mocniej oblegane" raczej wolę sam optymalizować zapytania.

Druga sprawa to obiekty oparte o ActiveRecord stoją trochę w sprzeczności z ideą OOP i dają publiczny dostęp do wszystkich swoich składowych. Sam np. nadpisałem Klasę Zend_Db_Record tak aby była możliwość określenia parametrów publicznych i prywatnych oraz zakresu wartości jakie przyjmują.

Trzecia sprawa to to, że początkowy zysk w postaci szybszego kodowania jest opłacony przez mniejszą przejrzystość kodu w przyszłości.

Z drugiej jednak strony muszę przyznać, że jest to kolosalne ułatwienie przy pisaniu i praca idzie znacznie szybciej - nie trzeba "klepać" ręcznie każdego małego obiektu.
Sh4dow
Nie znam framework'a zend'a ale propel dzieli sie na dwie czesci, ta ktora generuje klasy dla bazy danych i druga gdzie wykozystujesz juz gotowe obiekty, ktore nie za bardzo sa sprzeczne z OOP, raczej idealnie wpasowywują się w założenia OOP.
Osobiscie znam jedynie propela, jeśli chodzi o tego typu skrypty. Czy jest ktoś w stanie podać jakieś inne z którymi miał jakąś styczność ?
mike
Cytat(athabus @ 19.03.2007, 14:02:56 ) *
Zauważyłem, że już przy inicjacji takiej klasy wykonywane jest jedno dodatkowe zapytanie -> w tym przypadku Describe Table. Czyli np, aby odczytać wiersz o id=5 muszę wykonać 2 zapytania - 1 opisujące strukturę tabeli, drugie odczytujące wiersz.
W Propelu przy takich operacjach jest wykonywane tylko jedno zapytanie.
  1. <?php
  2.  
  3. $user = UserPeer::retrieveByPK(5);
  4.  
  5. ?>
I mamy użytkownika o identyfikatorze 5. Całościowo w jednym zapytaniu.

Cytat(athabus @ 19.03.2007, 14:02:56 ) *
Druga sprawa to obiekty oparte o ActiveRecord stoją trochę w sprzeczności z ideą OOP i dają publiczny dostęp do wszystkich swoich składowych. Sam np. nadpisałem Klasę Zend_Db_Record tak aby była możliwość określenia parametrów publicznych i prywatnych oraz zakresu wartości jakie przyjmują.
To akurat błąd w ZF a nie w idei ActiveRecordu.
Propel na przykład nie pozwala na takie rzeczy i ma settery i gettery do swoich właściwości.

Cytat(athabus @ 19.03.2007, 14:02:56 ) *
Trzecia sprawa to to, że początkowy zysk w postaci szybszego kodowania jest opłacony przez mniejszą przejrzystość kodu w przyszłości.
No coś ty?
  1. <?php
  2.  
  3. $author = new Author();
  4. $author->setFirstName("Jack");
  5. $author->setLastName("London");
  6. $author->save();
  7.  
  8. ?>
Moim zdaniem przejrzystość idzie tylko na plus.
athabus
Propela jeszcze nie próbowałem, ale z przykładów, które podajesz widzę, że moje przekonania są błędne. Niestety w ZF nie działa to, aż tak fajnie i trochę mnie to rozwiązanie zniechęcało.

Co do przejrzystości kodu to znowu -> jeśli tak jest jak piszesz, to zmienia postać rzeczy. W ZF tworzysz klasę dziedziczącą po Zend_Db_Table i ona nie definiuje ani pól ani ich typów. Później piszesz np.

  1. <?php
  2. $author->setField('name', 'Szymon');
  3. ?>

Tyle tylko, że pole name nie jest nigdzie zdefiniowane - po prostu musi istnieć w tabeli. To miałem na myśli.
Tak jak pisałem wcześniej udało mi się to nieco obejść i utworzyć nową klasę wiersza, która narzucała różne rzeczy.
Jeśli Propel definiuje cały kod klasy wraz z setterami i getterami to mnie to ostatecznie przekonuje aby przetestować to rozwiązanie.
splatch
Cytat(Sh4dow @ 19.03.2007, 13:36:04 ) *
czy czegos podobnego nie robi propel ? Bardzo ciekawe rozwiazanie. Niedawno znalazlem i zachwycam sie co jakis czas biggrin.gif Poza łatwością i przyjemnością w pisaniu, nie miałem okazji przetestować wszystkiego pod względem wydajności.

Edit:
Chociaz przy propel'u to by sie przydalo narzedzie do tworzenia tablic w XML'u. Coś podobnego w stylu tworzenia tablic w phpMyAdmin. Bo na większą skale jest to kosmar tak pisac biggrin.gif


Kod
propel_gen project-name creole
propel_gen project-name om


Krótki opis całości znajdziecie na moim blogu.

Cytat(Sh4dow @ 19.03.2007, 14:12:36 ) *
Nie znam framework'a zend'a ale propel dzieli sie na dwie czesci, ta ktora generuje klasy dla bazy danych i druga gdzie wykozystujesz juz gotowe obiekty, ktore nie za bardzo sa sprzeczne z OOP, raczej idealnie wpasowywują się w założenia OOP.

Dwa autonomiczne elementy propela to generator oraz runtime. Pierwszy do działania nie potrzebuje drugiego a drugi pierwszego, ponieważ mają one zupełnie inne zadania.

Cytat(mike_mech @ 19.03.2007, 14:15:21 ) *
W Propelu przy takich operacjach jest wykonywane tylko jedno zapytanie.
  1. <?php
  2.  
  3. $user = UserPeer::retrieveByPK(5);
  4.  
  5. ?>
I mamy użytkownika o identyfikatorze 5. Całościowo w jednym zapytaniu.

To akurat błąd w ZF a nie w idei ActiveRecordu.
Propel na przykład nie pozwala na takie rzeczy i ma settery i gettery do swoich właściwości.

News - w przyszłości mają pojawić się "lekkie obiekty", które nie będą miał standardowych setterów i getterów.

ORM to nie tylko AR, są różne strategie implementowania odwzorowań jak i ich zachowań. Spektrum problemu jest wbrew pozorom dość duże i obejmuje rzeczy tak elementarne jak klucze główne i tak złożone jak hierarchie dziedziczenia czy tak abstrakcyjne jak identyfikowanie raz stworzonego obiektu.

Myślę, że warto odwiedzających zachęcić do lektury PoEAA. Jeśli idzie o implementację mechanizmów O/R jest to czołowa pozycja, z której można wynieść bardzo wiele.

Myślę, że porównywanie Propela i Active Recorda to tak jak dyskusja o tym co jest lepsze - Abstract Factory czy Factory Method? Fakt jest jeden - to zależy.
ActivePlayer
A ja sobie napisałem swoją klasę (swego czasu opisywaną w phpsolutions) i to z niej korzystam. Zestaw Finderów wraz z obiektami (które wszystkie są dokładnie takie jak mi się to wymarzy, nic nie narzuca mi propel) to wg mnie najlepsza sprawa na jaką mogłem wpaść.
nospor
Ja mam podobnie (tak mi sie wydaje) jak ActivePlayer. Własna klasa, nawet nie wiem jak dziają te inne zendowe czy propelowe smile.gif
Klasa bazowa, która zawiera operacje zapisu i odczytu tabeli oraz zawiera wspolne pole dla wszystkich tabel (akurat u mnie w projektach tak mam).
Nastepnie dla danej tabeli tworze klase, ktora dziedziczy po bazowej i zawiera definicje dodatkowych pol tabeli, ktorych nie ma w bazowej. I to wszystko.
Jesli podczas zapisywywania danej tabeli potrzebuje wykonac jakies dodatkowe operacje, to nadpisuje metode save z bazowej i robie tam co mi potrzeba.

Rozwiązanie jest banalnie proste, elastyczne i przejrzyste. Jak musze cos kombinowa przy tabeli, to robie to tylko w danej klasie tabeli, nie latam juz po zadnych innych czesciach aplikacji.
Sh4dow
No to robisz prawie tak samo jak propel, Tylko ze propel generuje ci wszystko na podstawie xml'a. Masz obiekty dla tablic, masz plik sql zeby zrobic insert do bazy. Osobiście zapoznaje się jedynie z propelem, bo zend jakos mi nie podchodzi. I musze powiedziec ze trzeba sie troche przedstawic zeby wykozystac w pełni możliwości.
Jedyne co mnie martwi to wydajność której chyba na razie nikt nie sprawdził, jak bardzo tracimy na wydajności. Bo wygoda to jedno a wydajnosc to drugie. z czego chyba bardziej by mi zalezalo na tym drugim.
nospor
Cytat
Jedyne co mnie martwi to wydajność której chyba na razie nikt nie sprawdził, jak bardzo tracimy na wydajności.

To zalezy czy umiejetnie tego uzywasz czy nie. Przyklad:
mamy liste id. iterujemy tę listę i dla kazdego id z tej listy tworzymy obiekt reprezentujacy dany rekord dla danego id. Czyli dla kazdego id leci zapytanie do bazy - delikatnie rzecz mowiąc "średnio" optymalne smile.gif

Przyklad2 (edycja rekordu):
majac id rekordu ktory chcemy edytowac tworzymy dla niego obiekt a dane z obiektu przekazujemy do forma. Potem modyfikujemy dane w formie i zapisujemy. Dane z forma trafiaja do obiektu, a obiekt robi save w bazie - sposob przyjemny i zbytnio nie traci na optymalności. Jedyne zbedne zapytanie moze byc w momencie wcisniecia "zapisz" na formie i pobraniu danych rekordu, ktore i tak zachwile zostana zmodyfikowane (pod warunkiem ze form przeszedl walidacje). Ale mozemy sobie na to pozwolic

Przyklad3 (usuwanie rekordu):
Majac id rekordu do usunięcie tworzymy obiekt (wczytujemy dane z bazy) a nastepnie wywolujemy metodę Remove danego obiektu, ktora usuwa rekord z bazy. Zbedne wydaje się tu pobieranie danych rekordu, ktory i tak za chwile zostanie usuniety. Ale czy oby napewno? Czasami potrzebne nam są te dodatkowe dane zanim jeszcze usuniemy rekord. Chociazby poto by zapamietac informacje o tym, ze taki a taki user usunal taki a taki rekord

Podsumowujac:
Rozsądne używanie ActiveRecord umila życie programiście a jednocześnie nie obciąża zbytnio aplikacji
splatch
Pragnę nadmienić, że w przypadku Propela nie trzeba każdorazowo powoływać do życia instancji obiektu. W chwili gdy mamy do czynienia z odpytaniem na rzecz tabeli możemy wykorzystać obiekt Criteria i przy jego pomocy wymodelować zapytanie delete. Troszkę problematyczny jest update. W przypadku wstawiania danych zapytanie jest wykonywane dopiero po wykonaniu metody save(), a więc, bez zbędnych dodatków.
Sedziwoj
Może się wyda dziwne pytanie, ale czy obiekt nie może wyciągać danych z bazy, tylko kiedy są mu potrzebne a ich nie ma? Czyli nie podczas tworzenia a podczas odczytu (podkreślam kiedy ich nie ma).
Hacker
Eeeee...
@Sedziwoj czy mi się zdaje czy mówisz o leniwej konkretyzacji??
Sedziwoj
Ja piszę to co myślę, tak kochane 'wzorce projektowania' czy inne aspekty jak się okazało mi są obce, jak również zbędne, da się samemu wymyślić.

A chodzi mi o to co napisałem, chyba wyraziłem się jasno?
Że pobieramy dane nie przy tworzeniu obiektu, a przy wybieraniu nich.

A jako że nie mam zbytniego doświadczenia, pytam się o słuszność takiego postępowania, bo ma ono pewne zalety ale też wady. Tylko że ja mogę wszystkich nie widzieć (patrz brak doświadczenia) więc pytam, a że nie było to poruszane uważam, że jest na miejscu. (nie podaję tu swoich wywodów, bo oczekuję ich weryfikacji, ponieważ mogą okazać się moimi wymysłami tylko)
splatch
Cytat(Sedziwoj @ 28.03.2007, 01:25:53 ) *
Może się wyda dziwne pytanie, ale czy obiekt nie może wyciągać danych z bazy, tylko kiedy są mu potrzebne a ich nie ma? Czyli nie podczas tworzenia a podczas odczytu (podkreślam kiedy ich nie ma).


Takie zachowanie jest wskazane a nawet konieczne. Często jeden obiekt referuje do kilku innych, z kolei te referują gdzieś dalej. Gdyby tworzyć wszystkie obiekty w fazie inicjowania obiektu orm cały proces byłby znacznie wydłużony. Technika wczytywania na żądanie zwie się lazy load. Zachowuje się to dokładnie tak jak opisywałeś swój problem. Może na przykładzie propela.

  1. <?php
  2. // pobieramy obiekt, Propel wykona zapytanie:
  3. // SELECT FROM authors WHERE author_id = 11
  4. $author = AuthorsPeer::retrieveByPK(11);
  5. while($book = $author->getBooks()) {
  6. // przegladamy ksiazki, tutaj jest wykonywane zapytanie:
  7. // SELECT FROM books WHERE author_id = 11
  8. echo $book->getTitle() .'<br />';
  9. }
  10. ?>


Lazy load jest wygodny, aczkolwiek warto pamiętać by go nie nadużywać ponieważ w pewnym momencie jego wpływ na działanie aplikacji stanie się ujemny i inicjowanie obiektu na początku wszystkimi wartościami będzie bardziej wskazane.
pawel_k
@splatch - nie do konca dobry przyklad
pobierajac w propelu wiersz zwracany jest obiekt. problem w tym ze czesto chcesz pobrac np. tylko tytuly stron bez ich tresci, a samą treść tylko przy jej wyświetleniu w akcji show (która dajmy na to jest jeszcze w aplikacji cachowana). ustawiając w propelu lazy_load dla kolumny content w tabeli pages wartosc content pobierana jest tylko gdy wykonasz getContent() na obiekcie a nie zawsze gdy pobierasz dowolna ilosc obiektow pages.
jesli sie myle niech ktos mnie poprawi winksmiley.jpg
cicik
Mnie przed ORMami odstrasza jedna rzecz.
Jeżeli mam powiedzmy użytkownika, który należy do jakiejś grupy.
I teraz chce dostać jego imię, nazwisko i nazwę grupy do której należy to w przybliżeniu musiałbym zrobić coś takiego:

$user = new User($id);
$group = $user->getGroup();

Co powoduje wykonanie dwóch selectów zamiast jednego używającego złączenia tabel.
Poza tym wszędzie gdzie czytam o ORMach to zawsze podawany jest przykład taki jak powyżej, który ma być uzasadnieniem tego, że to jest fajne.
Ale co w sytuacjach kiedy potrzebuję mieć zapytanie z kilkoma złączeniami, limitem, sortowaniem, funkcjami specjalnymi typu CONCAT, funkcjami agregującymi itp? Mam wtedy dla takiego zapytania zrobić perspektywę i użyć wzorca Active Record do opisania tej perspektywy? Niby tak można ale wtedy w bazie będę miał 10 razy więcej perspektyw niż tabel...
athabus
Nie wiem jak to jest w innych ORM'ach ale właśnie zaczynam uczyć się propela i tam jest to dosyć ciekawie rozwiązane.

Z miejsca masz wygenerowane metody, służące do robienia joinow po foreign key. Możesz zarówno pobrać tylko jedną wybraną tablę, złączyć ją z jakąś tabelą, albo złączyć ją ze wszystkimi możliwymi tabelami.

Poza tym zawsze zostaje ci samemu odczytać odpowiednie dane wywołując odpowiednie zapytanie sql i użyć metody populateObject, która służy do wypełnienia obiektów ręcznie pobranymi danymi.

Ogólnie ORM'y (na przykładzie propela) mają swoje wady - chociażby dość duża ilośc kodu do przeparsowania (klasy propela są dość sporawe), ale jeśli chodzi o optymalność zapytań sql to zawsze idze je jakoś podrasować. Trzeba tylko sobie zdawać sprawę, że mechanizmy takie jak propel są po to, aby ułatwiać standardowe zadania i proste operacje - jeśli chodzi o te bardziej złożone to nikt tego za programistę nie zrobi.

Do niedawna miałem podobne zdanie do Ciebie, ale teraz gdy poznaje propela (dzięki właśnie temu tematowi) to zmieniam poglądy. Propel zdjął ze mnie konieczność pisania banalnego kodu do operacji CRUD i mogę się bardziej skupić nad logiką aplikacji jako całości. Jeśli chodzi o wydajność - to zgodzę się, że ORM nigdy nie będzie tak wydajny jak własne klasy - ale nie są to różnice na tyle duże aby sobie nimi zaprzątać głowę - co z tego, że aplikacja będzie chodziła 0,05s wolniej, jeśli dzięki temu zamiast pisać ją przez dwa tygodnie, zrobię to w 4-5 dni.
dr_bonzo
Nie, chocby w Railsach masz :include => 'group' i wykona ci zapytanie z JOINEm do grup przy znajdywaniu usera (User::find($id)). Dodatkowo dodajesz ORDER i LIMITY. Po SQLu tez da sie znalezc obiekty
Yacho
Cytat(athabus @ 19.03.2007, 15:02:56 ) *
Trzecia sprawa to to, że początkowy zysk w postaci szybszego kodowania jest opłacony przez mniejszą przejrzystość kodu w przyszłości.

No cos ty - to wyobraz sobie co sie dzieje w momencie kiedy masz aplikacje napisana z palca - i masz jakies 200 roznych SQL query - i klient jest bardzo przesądny i naprzyklad nie podoba mu sie pole czarny_kot w bazie danych - musisz zmienic 200 zapytań - w propelu jeden tag XML i działasz... winksmiley.jpg

pozatym myślę ze idea AR i ORM jest inna niż wszyscy myśla tu - klasy ORM sa po to aby juz enkapsulować jakąs logike biznesowa - powstały po to aby zintegrowac warste funkcjonalności biznesowych z dotyczacych tych danych. obiekt ORM jest po to zeby zdefiniowac także akcje jakie z obiektem sa powiazane, jest gdzies pomiedzy warstwa danych a biznesowa - natomiast nie ma watpliwosci ze AR jest tylko do ujednolicenia dostepu do bazy - na mniejszym stopniu abstrakcji niż ORM ale znacznie wiekszym niz bawienie sie w zapytania...
athabus
Yacho nie dość, że cytujesz moją wypowiedź sprzed 2 miesięcy, to jeszcze była ona na temat AR a nie ORM tongue.gif

Tak jak tam pisałem odnosiłem się do AR na przykładzie ZF, z którym miałem okazję spędzić trochę czasu. Problem jak się tu pojawił to, to że w momencie zmiany nazwy pola w tabeli musiałbym poprawić wszystkie odwołania, które korzystały z tej tabeli - także akurat Twój przykład tutaj nie za bardzo był trafny.

Pod wpływem tego wątku zainteresowałem się ORM (konkretnie Propelem) o czym też zresztą pisałem już w tym wątku tongue.gif Powiem szczerze, że jestem pozytywnie zaskoczony tym rozwiązaniem - nie myślałem, że w PHP uda się takie coś popełnić. Właśnie kończę pierwszy projekt z wykorzystaniem Propel'a i to jest coś czego mi od dawna brakowało.

Co do ORM to nie podoba mi się przekonanie, że są one bez sensu bo przy skomplikowanych zapytaniach wykonują nieoptymalne operacje i są be. Wiadomo, że jeśli robisz joina po wielu tabelach, czy wykonujesz jakieś skomplikowane zapytanie, to automatix nie jest najlepszym wyjściem - ORM ułatwia korzystanie z bazy, ale nie zdejmuje z programisty konieczności myślenie i optymalizacji. Po prostu są rzeczy, które można zostawić Propelowi do zrobienia i są takie w których trzeba mu trochę pomóc.
W propelu podoba mi się to, że przewidziano możliwość własnego konstruowania zapytań czy dodawania logiki do klasy. Programowanie z Propelem to jest po prostu bajka.
Sokal
Myślę sobie teraz o ORM...

Według mnie jest to utrudnianie sobie życia. Chyba lepiej poznać SQL niż uczyć się metod, które działają tak samo jak polecenia w SQL-u... Argument? Mamy jakieś złożone zapytanie, przy pomocy takiego ActiveRecords tego nie zrobimy. No i co? Musimy się uczyć SQL-a lub szukać po internecie jak coś zrobić. A nie lepiej od razu poznać go? Aplikacja działa szybciej, bo nie odpala iluś tam metod zanim wykona zapytanie.

IMHO ORM jest ułatwieniem dla początkujących winksmiley.jpg
menic
Jestes w błedzie Misiu (a moze pingwinku;) )
Złozone zapytania? Ich raczej czesto nie piszemy.
Sokal
A co powiesz na to, że piszesz jakąś super złożoną aplikację. W bazie trudno się połapać a złożone zapytania to są co drugą linijkę w kodzie.

Nie zrobisz tego przy użyciu, np. activerecords. Co prawda masz tam metodę query(), ale jak jest activerecords to po co taka metoda? snitch.gif Skoro: złożone zapytania => "Ich raczej czesto nie piszemy."...

Według mnie lepiej korzystać np. z PDO winksmiley.jpg

// I jeszcze jeden argument:
Przez ORM kod aplikacji się wydłuża
bela
Cytat
// I jeszcze jeden argument:
Przez ORM kod aplikacji się wydłuża

kod? no prosze.

  1. <?php
  2. $news = NewsPeer::doSelect(new Criteria()); 
  3. ?>

jest dluzsze od selecta w sqlu?

poza tym, orm sprawia kod bardziej czytelnym

co do zlozonych zapytan, ja czesto ich nie uzywam, czasem zdarzaja sie join na dwoch poziomach, ktorych niestety propel jeszcze nie obsluguje. ale miejmy nadzieje ze propel 2.0 bedzie niebawem smile.gif
menic
No to zaczynamy:
Sam AR moze i jest trudniejszy i bez sensu przy PDO, ale juz odpowiednio zbudowany ORM to juz inna bajka. Przyklady beda sie opierac na moim skrypcie. Dodatko do pelni szczescia potrzebne jest np. PHPIDE aby ladnie podpowiadalo metody obiektu snitch.gif Zacznijmy od tego ze strukture bazy danych definiujemy podobnie jak w propelu w xmlu. Na podstawie tego sa generowane odpowiednie klasy modelu. Najpierw "tworzymy" zapytanie
  1. <?php
  2. $oNews = new NewsModel();
  3. $oNews->addWhere( NewsModel::CAT_ID, swRequest::Get( 'id' ) );
  4. $oNews->addJoin( NewsModel::AUTHOR_ID, UsersModel::ID, 'LEFT' );
  5. $oNews->addJoin( NewsModel::CAT_ID, News_categoriesModel::ID, 'LEFT' );
  6. $aNews = $oNews->selectJoin();
  7. ?>

Mamy juz pobrane dane do $aNews. Wpisujujac $aNews-> otrzymujemy z podpowiedzi cala liste dostepych kolumn. Bo kazda kolumna ma metode getKolumna(). Dodatkowo dla dolaczonych tablel najpierw $aNews->joinJakasKolumna()->jakasKolumna() Oczywiscie wszystkie metody podpowiada nam eclipse. Tak by wygladala sprawa z pobieraniem danych. Przejdzmy teraz moze do ich dodawania snitch.gif
  1. <?php
  2. $oNews = new NewsModel();
  3. $oNews->setAuthor_id( 1 );
  4. $oNews->setCat_id( swRequest::Post( 'news_categories_id' ) );
  5. $oNews->setContent( swRequest::Post( 'content' ) );
  6. $oNews->setCREATED_AT( time() );
  7. $oNews->setTitle( swRequest::Post( 'title' ) );
  8. $oNews->insert();
  9. ?>
No i znowu tutaj kazda metoda odpowiada kolumnie w bazie danych. Dodatkowo mamy tutaj filtrowanie danych, tak wiec nie wstawimy jakiegos stringa do kolumny ktora oczekuja liczbe. I powiedz mi ze to jest niewygodne to cie normalnie nie wiem co tongue.gif
Sokal
Dla mnie to zawsze będzie niewygnodne, co z tego, że podpowiada mi składnie...

Więcej czasu zabiera wykonywanie zapytań winksmiley.jpg
menic
Co z tego? Np. to ze nie musisz pamietac nazw wszystkich tabel ani kolumn w bazie danych. To ze masz wieksza kontrole. To ze jest wygdniej tongue.gif Dorosniesz to zrozumiesz (joke) winksmiley.jpg
webik
Witam

Ot dorzuce swoje 3 grosze.... Osobiście używam PEAR DB_DataObject... Bardzo mnie sie podoba mialem troch problemów tyczącyc sie pierwszegoo uruchomienia i pierwszego utworzenia klas odwzorowujacych tabele.... Ale teraz wszystko idzie gładko..... Wszystko tworzy sie automatycznie pozniej tylko wykorzystuje klasy... Do tej pory nie zauważylem nadmiaru zapytań chciaż czasem jestem zbyt wyrozumiały wobec ilośici zapytań generowanych przez moj kod... Wczećniej uzywałem ADOdb i teraz wydaje mnie sie ze teraz ograniczyłem liczbe zapytań.... Kod też staje sie bardziej przejżysty ot chodźby pobranie usera:

  1. <?php
  2. //$id = primary key;
  3. $user = DB_DataObject::factory('users_desc');
  4. $user->get($id);
  5. ?>


i w objekcie user mam odrazu wszystko, warunki nie ma problemu:

  1. <?php
  2. $user = DB_DataObject::factory('users_desc');
  3. $user->id = $id;
  4. $user->online = 1;
  5. $user->find();
  6. ?>


cala struktura klasy na podstawie bazy jest przygotowywana z pommocą skryptu.... wiec zero pracy do wykonania... No chyba że chcemy jekies specjalne warunki przy dodawaniu do bazy... validatory nie napisza sie same....

wydaje mnie sie proste i przyjemne...

Ale moze to tylko przyzwyczajenie....

Pozdrawiam
mike
~Sokal a dlaczego uważasz że ORM jest dla osób nie znających SQL'a?
Tak się składa że jest dokładnie odwrotnie. Nie podejdziesz do żadnego ORM'a nie mając solidnych podstaw i wiedzy o SQL.

"IMHO ORM jest ułatwieniem dla początkujących winksmiley.jpg" - to Twoja opinia. A praktyka pokazuje że żaden większy bądź duży projekt nie jest pisany bez ORM'a
Już pomijam PHP, w Java na przykład większość aplikacji śmiga na Hibernate.
splatch
Cytat(Sokal @ 23.05.2007, 21:04:59 ) *
Dla mnie to zawsze będzie niewygnodne, co z tego, że podpowiada mi składnie...

Więcej czasu zabiera wykonywanie zapytań winksmiley.jpg

To po cholerę tu siedzisz, pytam? To forum to niby PRO więc się nie zachowuj jak dziecko i nie strzelaj fochów, że coś Ci się nie podoba i basta. Po cholerę wcinałeś się do tego wątku, tylko po to, żeby pokazać swoje wstecznictwo i ciemnotę? Jeśli nie masz więcej argumentów przeciw to, proszę, zamknij się i nie wtrącaj z byle gównem.

Ps. Jestem za usunięciem postów-śmieci z tego wątku (w tym i mojego).
athabus
splatch ty jakiś agresywny ostatnio jesteś blink.gif

Sokal - ORM nie jest po to aby nie uczyć się SQL. Ideą (tak mi się przynajmniej wydaje) to zdjęcie z programisty powtarzania ciągle tych samych operacji na bazie danych. Ciagłego pisania banalnych selectów itd. W PHP w porównaniu z innymi językami duży procent rzeczy, które robisz są "banalne", dlatego, że nie ma narzędzi automatyzujących pracę, albo mało osób z nich korzysta.

Powiem szczerze, że czasami jak pisze jakąś prostą stronkę to już mi się chce za przeproszeniem rzygać jak muszę napisać kolejny obiekt DAO, który w zasadzie robi to samo co inne tylko ma trochę inne nazwy pól itp. Dzięki Propelowi, frameworkom itd itp możesz skupić się na tych bardzie zawiłych rzeczach, a te rutynowe zostawiasz odpowiedniemu narzędziu.

Co do tego, że ORM jest dla osób nie znających SQL to mam takie zdanie jak Mike - żeby napisać dobrze coś w ORM trzeba na prawdę orientować się jak działa SQL i w ogóle baza danych. Trzeba wiedzieć, kiedy użyć gotowych rozwiązań ORM, a kiedy warto rozszerzyć daną klasę np. o pobieranie kolekcji nietypowych elementów.

Przykład z życia - masz sklep internetowy w którym produkty przynależą do różnych kategorii, mają różne stawki vat, marki, cechy. Liczba cech produktu jest zmienna. Każdy produkt ma różne progi rabatowe itd itp. Stajesz przed zadaniem pobrania x produktów z bazy z pełną informacją (czyli dodatkowe cechy, progi rabatowe itd). Gdybyś tutaj użył ORM'a bez własnej inwencji to położyłbyś bazę na łopatki ilością zapytań. Pół dnia zajęło mi, aby to zoptymalizować, napisać własne metody pobierania i wypełniania obiektów itd. Ale skutek jest taki, że dowolną ilość obiektów z bazy pobieram 2 zapytaniami Wcześniej jednak musiałem użyć tabel przejściowych, trochę cachowania itd. Mechanizmy Propela pozwoliły mi przebrnąć przez całe zadanie w miarę wygodnie - ale na pewno nie rozwiązały same mojego problemu - po prostu były punktem wyjścia. Swoją drogą było to fajne doświadczenie, bo rozwiązując kolejne problemy przejrzałem kod propela wzdłuż i wszerz - pewne rzeczy wydawały mi się na początku dziwne, ale potem często zauważałem ich uniwersalność i możliwość dostosowania całego narzędzia do swoich potrzeb.
eai
Nie ukrywam, temat dość ciekawy.
Nie wiem jednak czy dobrze to zrozumiałem, a nie chce tkwić w błędzie dlatego napisałem:
  1. <?php
  2.  
  3. class Query
  4. {
  5.  public static function Exec ($sql)
  6.  {
  7. if(mysql_connect('localhost','root', 'idesql'))
  8. {
  9.  if(mysql_select_db('test'))
  10.  {
  11.  return new ORM(mysql_query($sql));
  12. }
  13. }
  14. }
  15. }
  16.  
  17. class ORM
  18. {
  19.  private $__dquery = array();
  20.  
  21.  public function __construct($query)
  22.  {
  23.  $this->__dquery = $query;
  24. }
  25.  
  26.  public function select()
  27.  {
  28. if($array = mysql_fetch_assoc($this->__dquery))
  29. {
  30.  return new Data($array);
  31. }
  32.  
  33. return false;
  34. }
  35. }
  36.  
  37. class Data
  38. {
  39.  private $__darray = array();
  40.  
  41.  public function __get($name)
  42.  {
  43. if(empty($this->__darray)) { return false; }
  44.  
  45.  if(array_key_exists($name, $this->__darray))
  46.  {
  47. return $this->__darray[$name];
  48.  }
  49. }
  50.  
  51.  public function __construct($array)
  52.  {
  53.  $this->__darray = $array;
  54. }
  55. }
  56.  
  57.  
  58.  
  59. $table = Query::Exec('SELECT * FROM `tabela`');
  60.  
  61. while($row = $table->select()) {
  62. echo $row->nr . '; ';
  63. echo $row->imie . '; ';
  64. echo $row->nazwisko . ' <br>';
  65. }
  66.  
  67.  
  68. ?>


Jest to oczywiście bardzo prosty przykład, posiadający jedynie możliwośc pobierania wyników.

Moje pytanie brzmi: Czy ide w dobrym kierunku czy kompletnie nie zrozumiałem ORM?
splatch
Cytat(eai @ 31.05.2007, 15:10:14 ) *
Moje pytanie brzmi: Czy idę w dobrym kierunku czy kompletnie nie zrozumiałem ORM?


Idziesz w prawie dobrym kierunku. smile.gif
Ideą stosowania mapowań jest wykluczenie klepania SQLa na każdą potrzebę, a w tym momencie, mimo tego, że wynik masz reprezentowany w postaci obiektu, a nie różni się to od:
  1. <?php
  2. $rs = mysql_query($sql);
  3. while ($row = mysql_fetch_object($rs)) {
  4. echo $rs->id .' '. $rs->name .'<br />';
  5. }
  6. ?>


Owszem, umiejętność interpretacji każdego zapytania to cenna funkcjonalność, ale nie zapominaj o tym, że zależy Ci na obiektach jako takich a nie płaskich strukturach pokroju tablicy, a taki efekt uzyskujesz korzystając z __get (zwracasz po prostu kolumnę z wyniku nie zwracając uwagi na to z jakiego obiektu to jest property). Zwróć uwagę, że tu nie ma obiektu. Nie możesz odczytanych wartości zmodyfikować i zapisać.
Obiekt Query może się przydać przy mapowaniu zapytań, ale raczej nie przy ich interpretowaniu.

Kilka przykładów użycia "klasycznego" ORM:
  1. <?php
  2. // Użycie sesji, na podobę Hibernate
  3. // zauważ, że relacje są przeźroczyste
  4. $factory = SessionFactory::build(new PropertiesConfiguration('php-hibernate.ini'));
  5. $session = $factory->getSession();
  6.  
  7. $book = $session->load('Book', 11);
  8. $authors = $book->getAuthors(); // tutaj oczekujemy złączenia po relacji M:N
  9. $book->setTitle('[nakład wyczerpany]' . $book->getTitle());
  10. $book->setAvailable(false);
  11. $authros[0] = new Author('Stanisław', 'Lem');
  12.  
  13. $session->flush(); // wymuszamy zapisanie zmian
  14.  
  15. // uproszczony przykład użycia Table Data Gateway + Row Data Gateway
  16. // relacje M:N są obsługiwane ręcznie
  17. $book = BooksPeer::retrieveByPk(11);
  18. $authors = $book->getAuthors();
  19. $book->setTitle('[nakład wyczerpany]' . $book->getTitle());
  20. $book->setAvailable(false);
  21. // dobieramy się do tabelki pośredniej pomiędzy autorami a książkami
  22. $authros[0]->getProxyForBook(11)->delete();
  23. $authros[0] = new Author('Stanisław', 'Lem');
  24.  
  25. $authros[0]->createProxyForBook(11); // przywiązujemy autora do książki
  26. $book[0]->save(); // ten zapis załatwia nam wszystko
  27. ?>


Pamiętaj, że różnice implementacji przy różnych ORMach są czasami olbrzymie, zawsze możesz znaleźć swoją własną implementację bazując na dostępnych wzorcach.
nasty
Witam,
Chciałbym się odnieść do wypowiedzi paru osób które uważają ze ORM-y to tylko ułatwienie dla programisty, i ze jest ucieczka od nauki SQL-a.

Najważniejszą idea systemów ORM jest wspomaganie idei Domain-Driven-Develpment (DDD) która przeważnie jest podzielona na warstwy takich jak:
  • Business Layer
    • Business Entities
      Warstwa/część odpowiadająca za reprezentacje obiektów systemu (Entities) w postaci obiektow POJO/POCO/PO[x]O/etc... jak np. Customer, Book, Author...
    • Business Logic
      Warstwa ta odpowiada za operacje na wspomnianych Entities. I tu ORM-y sa bardzo przydatne, gdyż warstwa ta powinna być niezależną od warstwy dostępu do danych ale mieć w tym samym czasie możliwość operowania na danych zawartych w wspomnianych Entities. Klasy w tej warstwie komunikują się z baza za pomocą innych klas które są w warstwie Data Access Layer.
  • Data Access Layer
    Tu sa klasy DAO, ktore za pomoca ORM-a wypelniaja objekty z warstwy Business Enties odpowiednimi danymi.
Używając tradycyjnych metod dostępu do danych byłoby bardzo ciężko dobrze wymodelować warstwę logiki biznesowej bo np. powiedzmy ze Książka może dostać zniżkę tylko w wypadku kiedy jest kupowana w ilości x/miesiąc oraz ma Dostawce który jest na liście stabilnych dostawców. W tym przypadku używając reprezentacji danych w postaci obiektów, łatwo jest wymusić taka logikę na aplikacji na wiele sposobów takich jak używanie systemu workflow.

Drugim bardzo ważnym argumentem przemawiającym za ORM-ami jest zasada DRY (Don't Repeat Yourself). gdyż obiekty z Business Entities nierzadko biorą udział w Service Layer czyli w warstwie odpowiedzialna za eksponowanie funkcjonalności aplikacji za pośrednictwem Web Services. Używając SQL-a i tak byś musiał operować na obiektach by móc reprezentować dane w wspomnianej Service Layer, tak wiec musiałbyś najpierw wyciągać dane z tych obiektów, następnie zapisywać do bazy SQL-em a w razie potrzeby znowu wyciągać te dane sql-em i zapisywać do obiektów. UI tez czesto uzywa Business Entities...

I jeszcze jedno: używając systemu ORM, możemy wymusić walidacje danych z poziomu samych obiektów poprzez umieszczanie logiki walidacyjnej w setter-ach. W przypadku SQL-a byłoby kilka if() else() przed zapisem.

Dla tych którzy maja bardzo duże wątpliwości co do ORM-ow zalecam przyjrzenie się bardziej dojrzałym produktom takim jak (N)Hibernate, gdzie to ORM może zapisywać dane do prywatnych pól, które są i tak nie eksponowane przez obiekt a wykorzystywane w operacjach logicznych.

Pozdrawiam
Sokal
Chyba mnie przekonaliście do ORM-a winksmiley.jpg
Propel jest zajebiaszczo prosty w obsłudze, a możliwości są wielkie.
Miałem po prostu złe doświadczenia z ORM'em po poznaniu CodeIgniter'a. A kiedy chciałem poznać Propel to miałem same problemy, a to nie ma rozrzerzenia PHP - xslt (które było) a to co innego ...

W piątek spróbowałem jeszcze raz, a wcześniej jakiś tydzień temu w Symfony. Wszystko działa super smile.gif

//
Za moje poprzednie posty przepraszam.
Martio
Jakie znacie lub macie u siebie zaimplementowane sposoby rozwiązania problemu z relacjami pomiędzy tabelami? Jak rozwiązujecie konieczność pobrania danych z bazy danych przy złożonym warunków opierającym się o dwie tablice?
SongoQ
Takie cos jest w ORMach zaimplementowane. Patrz np propel http://propel.phpdb.org/trac/wiki/Users/Do...3/Relationships
NuLL
lub w phpDoctrine smile.gif
splatch
Cytat(splatch @ 31.05.2007, 18:40:38 ) *
Pamiętaj, że różnice implementacji przy różnych ORMach są czasami olbrzymie, zawsze możesz znaleźć swoją własną implementację bazując na dostępnych wzorcach.


Wystarczy zajrzeć pod wspomniany adres..

Data Source Architectural Patterns Table Data Gateway, Row Data Gateway, Active Record, Data Mapper.
Object-Relational Structural Patterns Identity Field, Foreign Key Mapping, Association Table Mapping, Dependent Mapping, Embedded Value, Serialized LOB, Single Table Inheritance, Class Table Inheritance, Concrete Table Inheritance, Inheritance Mappers.
Object-Relational Metadata Mapping Patterns Metadata Mapping, Query Object, Repository.
g00fy
Cytat(cicik @ 27.04.2007, 08:15:45 ) *
Mnie przed ORMami odstrasza jedna rzecz.
Jeżeli mam powiedzmy użytkownika, który należy do jakiejś grupy.
I teraz chce dostać jego imię, nazwisko i nazwę grupy do której należy to w przybliżeniu musiałbym zrobić coś takiego:

$user = new User($id);
$group = $user->getGroup();

Co powoduje wykonanie dwóch selectów zamiast jednego używającego złączenia tabel.
Poza tym wszędzie gdzie czytam o ORMach to zawsze podawany jest przykład taki jak powyżej, który ma być uzasadnieniem tego, że to jest fajne.
Ale co w sytuacjach kiedy potrzebuję mieć zapytanie z kilkoma złączeniami, limitem, sortowaniem, funkcjami specjalnymi typu CONCAT, funkcjami agregującymi itp? Mam wtedy dla takiego zapytania zrobić perspektywę i użyć wzorca Active Record do opisania tej perspektywy? Niby tak można ale wtedy w bazie będę miał 10 razy więcej perspektyw niż tabel...


ormy obsluguja transakcje,rozne rodzaje fetchingu etc... btw , zawsze mozesz zrobc RAW SQL jesli jakies zapytania przez orm robia sie bardzo uciazliwe..
XvZOK
A jak Propel radzi sobie z dziedziczeniem w klasach ?

Przykladowo mam klase
Contractor i dziedziczy po niej Client oraz Supplier

Dostawca i klient maja wiele wspolnych pol wiec warto by bylo
zastosowac tu relacje 1-1.
W efekcie mamy 3 klasy w tym 2 dziedziczace i odpowiadajace im tabele.

O ile nie ma problemu z np.: wstawieniem listy transakcji
do klienta (ralacje 1-n) to nie wiem czy propel
poradzi sobie w sytuacji kiedy to 1 klasa bedzie de facto zapisywac do 2 tabel ?

Jakies doswiadczenia w tym temacie ?
Moze inne ORM niz propel ?




2 temat to kwestja konwersji UML do schematu bazy danych.
Googluje juz od kilku dni ale jedyne co znalazlem to MetaL.
Nie dziala on jednak rewelacyjnie i konwertuje to swojego formatu a nie do schema.xml znanego z propela.
Sedziwoj
Cytat(XvZOK @ 30.07.2007, 16:53:15 ) *
2 temat to kwestja konwersji UML do schematu bazy danych.
Googluje juz od kilku dni ale jedyne co znalazlem to MetaL.
Nie dziala on jednak rewelacyjnie i konwertuje to swojego formatu a nie do schema.xml znanego z propela.

A może coś opisanego tutaj ?
splatch
Cytat(XvZOK @ 30.07.2007, 16:53:15 ) *
A jak Propel radzi sobie z dziedziczeniem w klasach ?

Propel radzi sobie z dziedziczeniem w klasach, aczkolwiek nie jest to "wypasiona" opcja.

Gdyby nazywać to zgodnie z nomenklaturą jest to dziedziczenie zorganizowane na jednej tabeli z dyskryminatorem, czyli kolumną której wartości wskazują z czym mamy do czynienia. Opis wraz z diagramem UML - Single Table Inheritance.
Dokumentacja Propela:
Advanced Object Model.

Przykładowy kod:
Kod
            Client
         /         \
    Enterprise       PrivateClient
                       \
                      CompanyWorker



  1. <table name="client" abstract="true">
  2. <column name="client_type" type="INTEGER" inheritance="single">
  3.   <inheritance key="0" class="PrivateClient" extends="nazwabazydanych.Client"/>
  4.   <inheritance key="1" class="CompanyWorker" extends="nazwabazydanych.PrivateClient"/>
  5.   <inheritance key="2" class="EnterpriseClient" extends="nazwabazydanych.Client"/>
  6. </column>
  7. <column name="title" type="VARCHAR" size="100"/>
  8. </table>
XvZOK
Ponownie wróciłem do tematu.
Widzę, że tutaj nie za dużo się wydarzyło.

Ostatnio zrobilem release tematu podczas tworzenia
abstrakcyjnego kontrolera CRUD do ZF.
Dziwi mnie fakt ze podczas dyskusji o ORM
nikt nie wspomniał o wygodzie przy tworzeniu warstwy widoku.

Przykładowo bibloteka patForms potrafi na podstawie obj. propela
wygenerować nam formularz do wpisywania/edycji danych.
Możemy oczywiście go dowolnie edytować w pliku XML.

Obecnie stosuje zestaw Zend Framework + Propel + Smarty.
Zastanawiam się jednak nad PEAR::DBObject

Testowaliście obydwa pod względem wydajności, wygody użycia ?

Wspomnę jeszcze o DataGrid.
Co polecacie ? Propel dostarcza niby klasę pozwalającą na
integrację z DataGrid z PEAR ale od razu mówie.. wersja jest przestarzała
i lepiej wogóle jej nie ruszać. Ja straciłem 3 h, poznałem dokładnie budowę
DataGrid iw końcu napisałem prawie od nowa klasę integrującą.
Ale teraz efekt jest bardzo przyjemny.
athabus
Myślę, że o widoku nikt nie wspomniał, bo temat nie dotyczy widoku :-)

A tak na serio to jeśli już mówimy o wygodzie projektowania aplikacji działających w oparciu o ORM to dla mnie nic nie przebije generacji paneli administracyjnych w symfony

filmik

Kilka linii w pliku konfiguracyjnym i masz wszystko - przeglądanie, dodawanie danych, walidację danych, łączenie danych z wielu tabel po kluczach obcych itd itp.
Jak to pierwszy raz zobaczyłem to się popłakałem, że tyle czasu traciłem na takie bzdety ;-) Zwykły crud to przy tym zabawka.

Inny przykład też z symfony to umieszczenie danych testowych w tabeli z pliku yml - piękna sprawa przy robieniu pierwszych testów.
splatch
Kwestia ORM i widoku nie wiąże się pośrednio, ponieważ kluczowe są tu metadane i informacje o strukturach z których ORM korzysta.
Propel ułatwia nam zadanie ponieważ mamy wygenerowany kod z informacjami na temat powiązań itp (bodajże katalog metadata obok innych wygenerowanych klas).
W przypadku ActiveRecord informacje te są zapisane jako fragment definicji w modelu (has_many, many_to_many itp).

Wystarczy zatem bezpośrednio podpiąć się pod metadane i umiejętnie je wykorzystać a nie będziemy potrzebowali generatorów.

Kiedyś dawno, dawno temu dopisywałem adaptery wiążące Propel-Agavi-Smarty tak by tworzyć nowe widoki i wyszukiwarki możliwie łatwo. Dodatkowo powiązałem sobie etykiety z klas z i18n, przez co przy polach wyszukiwania nie musiałem męczyć się z dorzucaniem labeli. Robiły to za mnie po prostu pluginy dopisane do smarty.
Kod, który nie jest wierną kopią tego co napisałem aczkolwiek prezentuje zbliżoną funkcjonalność.
  1. {search for='NazwaKlasy' action=jakiś_url}
  2.  
  3. {field for=id} <- pole z mo&#380;liwo&#347;ci&#261; wpisania tylko intów
  4.  
  5. {field for=foreign} <- tu mi si&#281; pokazywa&#322; np select
  6.  
  7. {field for=someDate fromTo=true} <- a tu para data od, data do
  8. {/search}


Dodatkowym elementem, który sobie wytworzyłem było wiązanie np inputów z wartościami niektórych pól. Dzięki temu nie trzeba podawać atrybutu value, id i tak dalej, ponieważ wszystko to można wyciągnąć dynamicznie z requestu w samym pluginie.
  1. {input for=text}


Po stronie PHP dodałem jeszcze element który nazwałem, może niezbyt trafnie, wrapperem. Jego użycie było bardzo proste i sprowadzało się w poszczególnych akcjach do podobnego kodu:
  1. <?php
  2. $wrapper = new PropelWrapper($this->getAgaviContext());
  3. try {
  4. if ($mode == 'new') {
  5. $object = $wrapper->createAndBindObject('Invoice');
  6. } else {
  7. $object = $wrapper->readAndBindObject('invoice', 'nazwa_pola_z_id_obiektu');
  8. }
  9. // tu otwarcie transakcji 
  10. $object->save();
  11. // i zamknięcie
  12. return 'Success';
  13. } catch (WrapperException $e) {
  14. handleWrapException($e);
  15. } catch (PropelException $e) {
  16. handlePropelException($e);
  17. } catch (Exception $e) {
  18. handleException($e);
  19. }
  20.  
  21. ?>

Przy odrobinie wysiłku akcja mogła by sprowadzać się tylko do:
  1. <?php
  2. // tym kodem załatwiamy edycję
  3. class InvoiceEditAction extends InvoiceInnerAction {
  4.  
  5. }
  6.  
  7. // tym kodem dodawanie
  8. class InvoiceAddAction extends InvoiceInnerAction {
  9. }
  10.  
  11. // klasa bazowa dla operacji z fakturą
  12. class InvoiceInnerAction extends WrapperAction {
  13. // jedyna rzecz jakiej wymaga od nas wrapper
  14. protected function getClassName() {
  15. return 'Invoice'
  16. }
  17. }
  18.  
  19. // tym kodem listowanie
  20. class InvoiceListAction extends ListAction {
  21. protected function getClassName() {
  22. return 'Invoice'
  23. }
  24. }
  25. ?>



Napisanie takiego "czegoś" to na prawdę ciekawe zadanie a integracja z zewnętrznymi bibliotekami może dać na prawdę sporo możliwości. Np kod, który udało mi się stworzyć w końcu zaczęła używać osoba, która nie była programistą tworząc widoki od ręki bazując tylko na strukturze bazy danych. Jedyna rzecz jaką musiała potrafić to dobrze sklecić szablon Smarty. Programista wówczas pisał logikę i nie zawracał sobie głowy resztą.
Martio
Używam Zend Frameworka. Chciałbym oddzielić warstwę logiki biznesowej od warstwy dostępu do danych. Dla warstwy logiki biznesowej najlepiej pasowałoby zastosować wzorzec "Domain Model". Jak wykorzystać "Zend_Db_Table" wraz z "Zend_Db_Table_Row" jako warstwy dostępu do danych? Mogę prosić o praktyczne zastosowanie?
regis87
Testowałem różne dostępne rozwiązania ORM, najlepiej moim zdaniem wypada DoctrinePHP. Jest bardzo prosty w implementacji, wygodny, ma ogromne możliwości. Także jeżeli komuś zależy na takich "ułatwieniach" to zdecydowanie polecam. Ja jednak zostanę przy pisaniu zapytań i "czystym" PDO. Powód? Pod koniec moich testów odpaliłem sobie Apache Benchmark.

Na bazie testowej (tabele: artykuly, users, tagi, artykuly_x_tagi - jakie tu panują relacje chyba widac smile.gif ) porównałem wydajność dwóch aplikacji:
1) w moim frameworku (prosty mvc, sesje, pare bibliotek, widok obsluguje TemplateLite) prosta aplikacja pobierająca rekordy z bazy, zapytania w SQL poprzez PDO;
2) te same zapytania w Doctrine i wyniki wyprintowane, bez żadnej "obudowy" w postaci frameworka, także teoretycznie powinno być wydajniej

Wyniki - prawie czterokrotnie większa wydajność pierwszej opcji. Wniosek - ORM to piękna rzecz, ale w dużych projektach gdzie wydajność to priorytet, lepiej sobie darować.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.