Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Zasady pisania na forum Pro

Tematy na forum Pro mogą zakładać jedynie moderatorzy. W otwartych tematach może pisać każdy, kto ma coś fachowego do powiedzenia. Wszystkie posty nie wnoszące nic do tematu będą natychmiast usuwane, a ich autorzy dostaną ostrzeżenie.
Jeśli uważasz, że jakiś temat jest warty dyskusji na tym forum, zgłoś go w temacie Propozycje.

> ActiveRecord, ORM
seaquest
post
Post #1





Grupa: Przyjaciele php.pl
Postów: 790
Pomógł: 7
Dołączył: 6.02.2003
Skąd: Polska

Ostrzeżenie: (0%)
-----


Na początek po reorganizacji forum chcielibyśmy zaproponować wam temat dotyczący mapowania tabel z baz danych na obiekty w PHP.
Go to the top of the page
+Quote Post
4 Stron V   1 2 3 > »   
Start new topic
Odpowiedzi (1 - 74)
Sh4dow
post
Post #2





Grupa: Zarejestrowani
Postów: 569
Pomógł: 0
Dołączył: 17.08.2003
Skąd: Dąbrowa Górnicza

Ostrzeżenie: (0%)
-----


czy czegos podobnego nie robi propel ? Bardzo ciekawe rozwiazanie. Niedawno znalazlem i zachwycam sie co jakis czas (IMG:http://forum.php.pl/style_emoticons/default/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 (IMG:http://forum.php.pl/style_emoticons/default/biggrin.gif)

Ten post edytował Sh4dow 19.03.2007, 13:44:13
Go to the top of the page
+Quote Post
athabus
post
Post #3





Grupa: Zarejestrowani
Postów: 898
Pomógł: 48
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
Sh4dow
post
Post #4





Grupa: Zarejestrowani
Postów: 569
Pomógł: 0
Dołączył: 17.08.2003
Skąd: Dąbrowa Górnicza

Ostrzeżenie: (0%)
-----


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ść ?
Go to the top of the page
+Quote Post
mike
post
Post #5





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
athabus
post
Post #6





Grupa: Zarejestrowani
Postów: 898
Pomógł: 48
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
splatch
post
Post #7





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


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 (IMG:http://forum.php.pl/style_emoticons/default/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 (IMG:http://forum.php.pl/style_emoticons/default/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.
Go to the top of the page
+Quote Post
ActivePlayer
post
Post #8





Grupa: Przyjaciele php.pl
Postów: 1 224
Pomógł: 40
Dołączył: 6.07.2004
Skąd: Wuppertal

Ostrzeżenie: (0%)
-----


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ść.
Go to the top of the page
+Quote Post
nospor
post
Post #9





Grupa: Moderatorzy
Postów: 36 559
Pomógł: 6315
Dołączył: 27.12.2004




Ja mam podobnie (tak mi sie wydaje) jak ActivePlayer. Własna klasa, nawet nie wiem jak dziają te inne zendowe czy propelowe (IMG:http://forum.php.pl/style_emoticons/default/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.
Go to the top of the page
+Quote Post
Sh4dow
post
Post #10





Grupa: Zarejestrowani
Postów: 569
Pomógł: 0
Dołączył: 17.08.2003
Skąd: Dąbrowa Górnicza

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
nospor
post
Post #11





Grupa: Moderatorzy
Postów: 36 559
Pomógł: 6315
Dołączył: 27.12.2004




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 (IMG:http://forum.php.pl/style_emoticons/default/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
Go to the top of the page
+Quote Post
splatch
post
Post #12





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
Sedziwoj
post
Post #13





Grupa: Zarejestrowani
Postów: 793
Pomógł: 32
Dołączył: 23.11.2006
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


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).
Go to the top of the page
+Quote Post
Hacker
post
Post #14





Grupa: Zarejestrowani
Postów: 225
Pomógł: 0
Dołączył: 1.11.2005

Ostrzeżenie: (0%)
-----


Eeeee...
@Sedziwoj czy mi się zdaje czy mówisz o leniwej konkretyzacji??
Go to the top of the page
+Quote Post
Sedziwoj
post
Post #15





Grupa: Zarejestrowani
Postów: 793
Pomógł: 32
Dołączył: 23.11.2006
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


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)
Go to the top of the page
+Quote Post
splatch
post
Post #16





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
pawel_k
post
Post #17





Grupa: Zarejestrowani
Postów: 211
Pomógł: 3
Dołączył: 29.07.2005
Skąd: Szczebrzeszyn

Ostrzeżenie: (0%)
-----


@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 (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
cicik
post
Post #18





Grupa: Zarejestrowani
Postów: 219
Pomógł: 5
Dołączył: 18.07.2006
Skąd: Piekary Śląskie

Ostrzeżenie: (0%)
-----


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...
Go to the top of the page
+Quote Post
athabus
post
Post #19





Grupa: Zarejestrowani
Postów: 898
Pomógł: 48
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #20





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


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
Go to the top of the page
+Quote Post
Yacho
post
Post #21





Grupa: Zarejestrowani
Postów: 148
Pomógł: 0
Dołączył: 16.06.2003

Ostrzeżenie: (0%)
-----


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... (IMG:http://forum.php.pl/style_emoticons/default/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...
Go to the top of the page
+Quote Post
athabus
post
Post #22





Grupa: Zarejestrowani
Postów: 898
Pomógł: 48
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Yacho nie dość, że cytujesz moją wypowiedź sprzed 2 miesięcy, to jeszcze była ona na temat AR a nie ORM (IMG:http://forum.php.pl/style_emoticons/default/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 (IMG:http://forum.php.pl/style_emoticons/default/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.
Go to the top of the page
+Quote Post
Sokal
post
Post #23





Grupa: Zarejestrowani
Postów: 237
Pomógł: 1
Dołączył: 8.02.2007

Ostrzeżenie: (10%)
X----


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 (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)

Ten post edytował Sokal 23.05.2007, 17:58:15
Go to the top of the page
+Quote Post
menic
post
Post #24





Grupa: Zarejestrowani
Postów: 493
Pomógł: 0
Dołączył: 14.06.2003
Skąd: Tomaszów Lubelski/Rzeszów

Ostrzeżenie: (0%)
-----


Jestes w błedzie Misiu (a moze pingwinku;) )
Złozone zapytania? Ich raczej czesto nie piszemy.
Go to the top of the page
+Quote Post
Sokal
post
Post #25





Grupa: Zarejestrowani
Postów: 237
Pomógł: 1
Dołączył: 8.02.2007

Ostrzeżenie: (10%)
X----


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? (IMG:http://forum.php.pl/style_emoticons/default/snitch.gif) Skoro: złożone zapytania => "Ich raczej czesto nie piszemy."...

Według mnie lepiej korzystać np. z PDO (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)

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

Ten post edytował Sokal 23.05.2007, 18:12:27
Go to the top of the page
+Quote Post
bela
post
Post #26


Administrator PHPedia.pl


Grupa: Developerzy
Postów: 1 102
Pomógł: 2
Dołączył: 14.09.2003

Ostrzeżenie: (0%)
-----


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 (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
menic
post
Post #27





Grupa: Zarejestrowani
Postów: 493
Pomógł: 0
Dołączył: 14.06.2003
Skąd: Tomaszów Lubelski/Rzeszów

Ostrzeżenie: (0%)
-----


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 (IMG:http://forum.php.pl/style_emoticons/default/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 (IMG:http://forum.php.pl/style_emoticons/default/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 (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif)
Go to the top of the page
+Quote Post
Sokal
post
Post #28





Grupa: Zarejestrowani
Postów: 237
Pomógł: 1
Dołączył: 8.02.2007

Ostrzeżenie: (10%)
X----


Dla mnie to zawsze będzie niewygnodne, co z tego, że podpowiada mi składnie...

Więcej czasu zabiera wykonywanie zapytań (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
menic
post
Post #29





Grupa: Zarejestrowani
Postów: 493
Pomógł: 0
Dołączył: 14.06.2003
Skąd: Tomaszów Lubelski/Rzeszów

Ostrzeżenie: (0%)
-----


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 (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif) Dorosniesz to zrozumiesz (joke) (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
webik
post
Post #30





Grupa: Zarejestrowani
Postów: 24
Pomógł: 0
Dołączył: 1.05.2006
Skąd: Leżajsk\Kraków

Ostrzeżenie: (0%)
-----


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
Go to the top of the page
+Quote Post
mike
post
Post #31





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

Ostrzeżenie: (0%)
-----


~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 (IMG:http://forum.php.pl/style_emoticons/default/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.
Go to the top of the page
+Quote Post
splatch
post
Post #32





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


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ń (IMG:http://forum.php.pl/style_emoticons/default/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).
Go to the top of the page
+Quote Post
athabus
post
Post #33





Grupa: Zarejestrowani
Postów: 898
Pomógł: 48
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


splatch ty jakiś agresywny ostatnio jesteś (IMG:http://forum.php.pl/style_emoticons/default/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.
Go to the top of the page
+Quote Post
eai
post
Post #34





Grupa: Zarejestrowani
Postów: 367
Pomógł: 10
Dołączył: 20.05.2005

Ostrzeżenie: (0%)
-----


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?
Go to the top of the page
+Quote Post
splatch
post
Post #35





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


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. (IMG:http://forum.php.pl/style_emoticons/default/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.
Go to the top of the page
+Quote Post
nasty
post
Post #36





Grupa: Zarejestrowani
Postów: 634
Pomógł: 14
Dołączył: 27.05.2006
Skąd: Berlin

Ostrzeżenie: (0%)
-----


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
Go to the top of the page
+Quote Post
Sokal
post
Post #37





Grupa: Zarejestrowani
Postów: 237
Pomógł: 1
Dołączył: 8.02.2007

Ostrzeżenie: (10%)
X----


Chyba mnie przekonaliście do ORM-a (IMG:http://forum.php.pl/style_emoticons/default/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 (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

//
Za moje poprzednie posty przepraszam.

Ten post edytował Sokal 12.06.2007, 17:57:50
Go to the top of the page
+Quote Post
Martio
post
Post #38





Grupa: Zablokowani
Postów: 167
Pomógł: 2
Dołączył: 15.02.2004

Ostrzeżenie: (30%)
XX---


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?
Go to the top of the page
+Quote Post
SongoQ
post
Post #39





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

Ostrzeżenie: (0%)
-----


Takie cos jest w ORMach zaimplementowane. Patrz np propel http://propel.phpdb.org/trac/wiki/Users/Do...3/Relationships
Go to the top of the page
+Quote Post
NuLL
post
Post #40





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

Ostrzeżenie: (0%)
-----


lub w phpDoctrine (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
splatch
post
Post #41





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
g00fy
post
Post #42





Grupa: Zarejestrowani
Postów: 22
Pomógł: 0
Dołączył: 23.11.2004

Ostrzeżenie: (0%)
-----


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..
Go to the top of the page
+Quote Post
XvZOK
post
Post #43





Grupa: Zarejestrowani
Postów: 5
Pomógł: 0
Dołączył: 30.07.2007

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
Sedziwoj
post
Post #44





Grupa: Zarejestrowani
Postów: 793
Pomógł: 32
Dołączył: 23.11.2006
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


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 ?
Go to the top of the page
+Quote Post
splatch
post
Post #45





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


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>
Go to the top of the page
+Quote Post
XvZOK
post
Post #46





Grupa: Zarejestrowani
Postów: 5
Pomógł: 0
Dołączył: 30.07.2007

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
athabus
post
Post #47





Grupa: Zarejestrowani
Postów: 898
Pomógł: 48
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
splatch
post
Post #48





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


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ą.
Go to the top of the page
+Quote Post
Martio
post
Post #49





Grupa: Zablokowani
Postów: 167
Pomógł: 2
Dołączył: 15.02.2004

Ostrzeżenie: (30%)
XX---


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?
Go to the top of the page
+Quote Post
regis87
post
Post #50





Grupa: Zarejestrowani
Postów: 36
Pomógł: 0
Dołączył: 9.11.2003

Ostrzeżenie: (0%)
-----


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 (IMG:http://forum.php.pl/style_emoticons/default/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ć.
Go to the top of the page
+Quote Post
Sedziwoj
post
Post #51





Grupa: Zarejestrowani
Postów: 793
Pomógł: 32
Dołączył: 23.11.2006
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


@regis87

I moim zdanie się mylisz, jak jest duży projekt bez ORM to masakra.
A co do wydajności, to jak masz wiele do wielu to tak zawsze jest, ale pamiętaj że korzystając z ORM najbardziej zachłanne rzeczy można przepisać na niższy poziom, czyli wykorzystując tylko abstrakcję bazy danych.

Do tego tak często nie doceniane widoki (przez większość zwane perspektywami) się przy stosowaniu ORM bardzo przydają.

Bo nie można zaprzeczyć, że ORM jest bardziej obciążający niż prosty dostęp, ale tak samo programowanie obiektowe (w tym wspomniane MVC) też jest wolniejsze od proceduralnego, jednak jakoś nikt na to nie zwraca zbytniej uwagi, chyba że jest jakiś punkt gdzie wydajność siada, ale to się małe fragmenty kodu zmienia, nie całą aplikację.
"Nie używajmy ORM", to prawie jakby mówić "piszmy w asemblerze". Może trochę przesadzam, ale jak się nie przestawia korzyści, i gada głupoty że w dużych projektach to lepiej bez... to mnie to irytuje.
Oczywiście zawsze się znajdzie coś co musi być napisane w asemblerze, ale to są na prawdę specyficzne rzeczy, a nie typowe aplikacje.
Go to the top of the page
+Quote Post
Cysiaczek
post
Post #52





Grupa: Moderatorzy
Postów: 4 465
Pomógł: 137
Dołączył: 26.03.2004
Skąd: Gorzów Wlkp.




W 100% popieram. Za całą obiektową otoczką takiego Propela lecą zwykłe zapytania SQL, a jedynie konieczność utworzenie obiektów ze zwracanego wyniku lekko spowalnia. Lepiej zatem (jak mówi Sedziwoj) pisać z użyciem ORM, a potem jedynie odnaleźć bardzo czasochłonne operacje i je przepisać. Zauważ, że jak coś jest bardzo zasobożerne, to jest to zazwyczaj operacja na ogromnych ilościach danych na raz. Z autopsji powiem, bo dziś w nocy troszkę potestowałem, że operacje z wyszukiwaniem LIKE %xxx% na 250 000 rekordach to 3.49 s gołe zapytanie i 3.6 s Propel (wliczam utworzenie paczki z danymi).

Pozdrawiam.
Go to the top of the page
+Quote Post
splatch
post
Post #53





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Może w kwestii dużych projektów. Panowie nie zapominajmy, że duże projekty zazwyczaj stoją na dedykowanych maszynach, gdzie nie martwimy się tym, że nasz dostawca odetnie vhosta z racji na generowane obciążenie. Z drugiej strony - jakie są różnice czasowe, bo procentowo jest to dużo, ale czy będzie to odczuwalne dla użytkownika?
Nie pracowałem może w największych projektach, ale ilość linii kodu szła w tysiące czy też dziesiątki tysięcy. Gdyby każdy miał klepać zapytania, bo "tak jest wydajniej" to stracili byśmy na tym zbyt wiele czasu. Podstawą w takich wypadkach jest ORM i dobrze skonstruowane DAO, tak by nie pojawiały się metody duplikujące swe działania (pytanie - które DAO co może odczytywać). Zaoszczędzasz czas upraszczając sobie pracę z pozyskanymi danymi - w dalszym ciągu masz obiekty, w których możesz zawrzeć jakieś w miarę proste operacje, a nie półśrodki w postaci tablic bądź map. Chodzi o to, że gdy ORM stworzy Ci obiekt powiedzmy faktury - tworzysz metodę isPaid a w niej masz jakiś warunek. Normalnie, pisząc strukturalnie - ten warunek przerzuciłbyś do kontrolera bądź, co gorsza, widoku. Gdy coś się zmienia w sposobie uznawania płatności i masz ORM modyfikujesz tylko jedną metodę. Nie szukasz wszystkich warunków, gdzie dany typ danych się przewija.

Popatrzcie proszę na ORM przez perspektywę tego, co może dać nam obiekt (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) .
Go to the top of the page
+Quote Post
regis87
post
Post #54





Grupa: Zarejestrowani
Postów: 36
Pomógł: 0
Dołączył: 9.11.2003

Ostrzeżenie: (0%)
-----


Może źle to ująłem. Mówiąc o dużych projektach nie mam na myśli bardzo rozbudowanych aplikacji z ogromną funkcjonalnością. Chodzi mi raczej o serwisy, które wystawione są na działanie bardzo dużej liczby użytkowników, a więc wywołań. Sam rozmiar bibliotek ORM daje do myślenia - po skompilowaniu DoctrinePHP do pojedyńczego pliku, zajmuje on prawie 700KB. Bez kompilacji jest jeszcze gorzej, bo wszystko rozbite jest na nie dziesiątki, ale setki plików klas. Z tego co wiem podobnie wygląda to w przypadku Propela.

Ale... jakiś czas temu trafiłem na bibliotekę realizującą wzorzec ORM, o nazwie Pork. Jest bardzo mała, szybka... trzeba to przetestować (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

http://www.schizofreend.nl/Pork.dbObject
Go to the top of the page
+Quote Post
Cysiaczek
post
Post #55





Grupa: Moderatorzy
Postów: 4 465
Pomógł: 137
Dołączył: 26.03.2004
Skąd: Gorzów Wlkp.




W przypadku Propela masz kilka plików + te, które sam wygenerujesz.
Rozumiemy, o co chodzi z dużą ilością odwiedzin, ale w którym momencie upatrujesz koniec sensowności ORM? Ile odwiedzin dziennie?
Go to the top of the page
+Quote Post
regis87
post
Post #56





Grupa: Zarejestrowani
Postów: 36
Pomógł: 0
Dołączył: 9.11.2003

Ostrzeżenie: (0%)
-----


Nie potrafię tego oszacować. Ale kiedy wydajność staje się problemem, w ORM w pierwszej kolejności szukałbym oszczędności...
Go to the top of the page
+Quote Post
Cysiaczek
post
Post #57





Grupa: Moderatorzy
Postów: 4 465
Pomógł: 137
Dołączył: 26.03.2004
Skąd: Gorzów Wlkp.




Jeśli dysponujesz dedykowanym serwerem, to moim zdaniem problemy zaczną się gdzieś w okolicach kilkudziesięciu tysięcy odsłon dziennie. Bardzo mało serwisów osiąga takie liczby. Ja bym w tym wypadku zainwestował w jakiś cache dla modelu danych, czy nawet w cachowanie całych stron www. Dopiero gdyby to nie pomogło, szukałbym optymalizacji zapytań. Nie będę rzucał liczbami, ale np. forum.php.pl mimo, że jest popularnym, średniej klasy forum nie osiąga jeszcze pułapu, przy którym zdycha sprzęt ;p

Pozdrawiam
Go to the top of the page
+Quote Post
Martio
post
Post #58





Grupa: Zablokowani
Postów: 167
Pomógł: 2
Dołączył: 15.02.2004

Ostrzeżenie: (30%)
XX---


Cytat(Martio @ 26.02.2008, 02:54:43 ) *
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?


W sumie jakby nie było, to połączenie Zend_Db_Table_Row z DomainModel to wzorzec wypisz wymaluj.... ActiveRecord (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Mam pytanie do osób, które korzystają z wzroca Active Record. Czy implementujecie w nim logikę biznesową?

Przykład:

  1. <?php
  2. class Produkt extends ActiveRecord {}
  3. class Zamowienie extends ActiveRecord {
  4. public function obliczWartoscZamowienia() {
  5.  $produkty = $this->pobierzZamowioneProdukty();
  6.  
  7.  $wartosc = 0
  8.  
  9.  foreach ($produkty as $produkt) {
  10. $wartosc += $produkt->pobierzCene() * $produkt->pobierzIlosc();
  11.  }
  12.  
  13.  return $wartosc;
  14. }
  15. }
  16. ?>
Go to the top of the page
+Quote Post
menic
post
Post #59





Grupa: Zarejestrowani
Postów: 493
Pomógł: 0
Dołączył: 14.06.2003
Skąd: Tomaszów Lubelski/Rzeszów

Ostrzeżenie: (0%)
-----


@up: TAK
Go to the top of the page
+Quote Post
regis87
post
Post #60





Grupa: Zarejestrowani
Postów: 36
Pomógł: 0
Dołączył: 9.11.2003

Ostrzeżenie: (0%)
-----


Skończyłem testy, pork.dbObject. Jest imponujący pod względem wydajności i małych rozmiarów, ale ma ten mankament, że aby obsługiwać relacje pola w tabelach muszą być nazywane według ustalonego schematu. Ten schemat tak naprawdę wymusza PRAWIDŁOWE nazewnictwo pól: pole primary nazywa się ID_obiekt, pola będące kluczami relacji mają nazwy odpowiadających kluczy primary itd... ale wiadomo jak to wygląda w praktyce, rzadko zdarzają się tak ładnie skonstruowane bazy (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Autor mówi, że to właśnie takie ograniczenie pozwala na tę oszczędność kodu. Ale w planach ma dodanie funkcjonalności tworzenia relacji "ręcznie".

Ten post edytował regis87 2.03.2008, 22:50:56
Go to the top of the page
+Quote Post
Strzałek
post
Post #61





Grupa: Przyjaciele php.pl
Postów: 384
Pomógł: 6
Dołączył: 11.09.2004
Skąd: Grodzisk Mazowiecki

Ostrzeżenie: (0%)
-----


To może ja coś skrobnę od siebie, o moich doświadczeniach z ORM, a konkretnie z Doctrine. Obok wcześniej wspominanego Propela jest to jedeno z najpopularniejszych narzędzi tego typu. Doctrine przeciwieństwie do Propela nie generuje żadnego kodu. Oraz właściwie nie uwalnia nas do końca od pisania SQL. Jednak MASYMALNIE go uprasza i przyśpiesza. Mianowicie, w Doctrine definuje się każdą tablę np. tak (przykłady będą z dokumentacji)

  1. <?php
  2.  
  3. class Article
  4. {
  5. public function setTableDefinition()
  6. {
  7. $this->hasColumn('name', 'string');
  8. $this->hasColumn('content', 'string');
  9.  
  10. $this->index('content', array('fields' => 'content',
  11. 'type'  => 'fulltext'));
  12. }
  13. }
  14.  
  15. ?>
  16.  
  17. <?php
  18.  
  19. class Product extends Doctrine_Record
  20. {
  21. public function setTableDefinition()
  22. {
  23. $this->hasColumn('id', 'integer', 4, 'primary');
  24. $this->hasColumn('price', 'decimal', 18, array('min' => 0, 'max' => 1000000));
  25. }
  26. }
  27.  
  28. ?>


W metodzie setUp ustawia się relacje do innych Rekordów (czyli klas "odpowiadających" tabelom w db). Przykładowe wyciąganie z bazy danych wygląda tak:

  1. <?php
  2. $q = new Doctrine_Query();
  3. $q->from('User u')
  4. ->leftJoin('u.Group g')
  5. ->innerJoin('u.Phonenumber p WITH u.id > 3')
  6. ->leftJoin('u.Email e');
  7.  
  8. $users = $q->execute();
  9.  
  10. //używanie danych, przykładowo ilustruje jak to wygląda. Nie wiem jakie są pola w 
    bazie dancyh. 
  11. $users[0] -> name;
  12. $users[0] -> Phonenumber -> number;
  13. ?>


Gdzie zamiast nazw tabel podaje się nazwy rekordów. To jest właśnie DQL - Doctrine Query Language. Zapytanie zostaje parsowane do zwykłego zapytania SQL a następnie zostaje zwrócona tablica z obiektami rekordów wcześniej zadeklarowanych. Wreszcie możemy zapomnieć o babraniu się z wyciąganiem danych zwróconych przez zapytanie. Wystarczy takie zapytanie jak powyżej i mamy wszystko z głowy. Dostajemy tablicę z ładnymi obiektami. DQL dodatkowo oferuje inne możliwości jak np. INDEXBY.

Gdyby jednak okazało się że nie da rady wykonać zapytanie przez DQL. Mamy wtedy 2 możliwości. Użyć Doctrine_RawSql, gdzie piszemy właściwie normalne zapytanie, a na końcu podpinamy obiekty. Albo możemy po prostu z Doctrine wziąć obiekt PDO i użyć go jak za starych (dobrych) czasów (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg) Ja jak narazie tylko raz użyłem RawSql, a PDO? Szczerze to już nie pamiętam jak się z tego korzysta (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)

Tyle jeżeli chodzi o wyciąganie. Tworzenie i update rekordów jest również banalny i oczywiście odbywa się przez obiekty rekordu. Dodatkowo Doctrine posiada kilka pluginów które są naprawdę bardzo użyteczne i przydatne. Po więcej informacji odsyłam do dokumentacji.

Zaraz padną głosy że doctrine to krowa. Owszem, trochę to wszystko waży. Jeżeli chodzi jednak o wydajność nie poczułem żadnych niedogodności, więc to wszystko mi odpowiada (kolega mówił że jeden projekt składający się z 35 tabel napisał na doctrine (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) . Projekt się szybko rozwija. Autorzy zapowiadają że niedługo pojawi się nowa wersja z nowym parserem DQL, który ma być szybszy, chyba ma posiadać nawet jakieś nowe możliwości.

Generalnie, polecam Doctrine. Warto zainteresować się tym ORM.
Go to the top of the page
+Quote Post
Sedziwoj
post
Post #62





Grupa: Zarejestrowani
Postów: 793
Pomógł: 32
Dołączył: 23.11.2006
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Cytat
$users[0] -> Phonenumber -> number;


Czyli mam rozumieć, że on korzysta z stdClass? Czy działa podpowiadanie składni? Bo jak nie to zupełnie niewygodne jest takie coś w porównaniu do Propela.
Do tego trzeba się nauczyć dodatkowej składni DQL. Pisać mimo wszystko w PHP, w Prpelu jest to za darmo generowane, nie wiem czemu ale czuję że ludzie uciekają od złożoności działania, tracąc prostotę użytkowania.

Jakoś nadal nie widzę aby Doctrine był w czymś lepszy od Propela (wydajność nie biorę jako składową oceny)
Może ktoś mi napisze dlaczego miałby być lepszy od Propela, jest na pewno lepszy od ręcznego klepania, ale chyba szuka się najlepszych rozwiązań.
Go to the top of the page
+Quote Post
Strzałek
post
Post #63





Grupa: Przyjaciele php.pl
Postów: 384
Pomógł: 6
Dołączył: 11.09.2004
Skąd: Grodzisk Mazowiecki

Ostrzeżenie: (0%)
-----


Cytat
Czyli mam rozumieć, że on korzysta z stdClass?


Nie rozumiem? Czemu niby? $users jest obiektem Doctrine_Colletion. Doctrine_Collection posiada kolekcje obiektów User (wcześniej zdefiniowanych przez nas rekordów). User natomiast ma zdefiniowane przykładowo relację do Phonenumbers. Właściwość Phonenumber obiektu user przechowuje obiekt Phonenumber. Wszystko bardzo logiczne.

Cytat
Do tego trzeba się nauczyć dodatkowej składni DQL.


No cóż. Nie przesadzajmy. Czy naprawdę musisz się uczyć całkowicie nowej składni? Po tyg. użytkowania wszystko staje się proste. Tworzysz łańcuszej jak zwykły SQL. Ba, lepiej. Masz mniej pisania, bo nie musisz przy joinach pisac ON ... bo relacje masz wczesniej zadeklarowane i same są dołączane przez parser DQL.


NIe napisałem że Doctrine jest lepsze od Propela. Sam przy wyborze ORM, przeczytałem trochę dokumentacji Propela i Doctrine i wybrałem opcje drugą. Nie mogę sie do końca wypowiadać o Propelu bo go nie używałem i nie znam. Wiem jednak (od samych użytkowników propela) że np. jakieś większe JOINY to już problem. Dodatkowo dla mnie pomyłką jest coś takiego:


  1. person.gender = 'M' AND (person.location IN ('Birmingham', 'Coventry') OR person.location = 'Manchester') AND (person.enabled <> 0) AND person.age > 16


W propelu żeby uzyskać coś takiego trzeba napisać:

  1. <?php
  2. $c = new Criteria();
  3. $crit0 = $c->getNewCriterion(PersonPeer::GENDER, 'M');
  4. $crit1 = $c->getNewCriterion(PersonPeer::LOCATION, array('Birmingham', 'Coventry'), Criteria::IN);
  5. $crit2 = $c->getNewCriterion(PersonPeer::LOCATION, 'Manchester');
  6.  
  7. // Perform OR at level 1 ($crit1 $crit2 )
  8. $crit1->addOr($crit2);
  9. $crit3 = $c->getNewCriterion(PersonPeer::ENABLED, 0, Criteria::NOT_EQUAL);
  10. $crit4 = $c->getNewCriterion(PersonPeer::AGE, 16, Criteria::GREATER_THAN);
  11.  
  12. // Perform AND at level 0 ($crit0 $crit1 $crit3 $crit4 )
  13. $crit0->addAnd($crit1);
  14. $crit0->addAnd($crit3);
  15. $crit0->addAnd($crit4);
  16.  
  17. // Remember to change the peer class here for the correct one in your model
  18. $c->add($crit0);
  19. $result = TablePeer::doSelect($c);
  20. ?>


Kod wygenerowany przez: http://propel.jondh.me.uk/ Halo? Mieliśmy sobie ułatwiać pracę i skracać czas.

Ale tak jak mówię. Nie używałem Propela więc cieżko jest mi coś więcej powiedzieć. Używam natomiast Doctrine i uważam to za świetne narzędzie. Polecam zerknąć do dokumentacji, poczytać.
Go to the top of the page
+Quote Post
athabus
post
Post #64





Grupa: Zarejestrowani
Postów: 898
Pomógł: 48
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Doctrine nie używałem więc trudno mi porównać prostotę pisania. Ale skłonię się ku opinii Sedziwoja. Dla mnie w Propelu największym plusem są właśnie klasy "szkieletowe" z możliwością ich rozbudowania. Najwięcej czasu w projekcie zawsze traciłem na tworzeniu prostych zapytań. Jest to (obok formularzy) jedna z najbardziej monotonnych części projektu.
Propel generuje w zasadzie wszystko co się da zrobić z automatu, a programiście pozostaje tylko dopisanie ewentualnych nakładek i dodatków.

Genialną zaletą Propela jest właśnie podpowiadanie składni (propel pozwala opcjonalnie nawet na dodanie komentarz phpDoc więc w PDT podpowiadanie działa nawet do zagnieżdżonych obiektów). Dzięki podpowiadaniu składni, nawet po powrocie do projektu po kilku miesiącach łatwo jest ogarnąć operacje na bazie.

Wady propela jak dla mnie są dwie:
- dosyć skomplikowane tworzenie niektórych zapytań (np. gdy przychodzi do łączenia Criterion'ów to do tej pory muszę czasami zaglądać do manuala)
- wydajność (chodzi o samo php, bo zapytania są raczej standardowe) - choć tak na prawdę wydajność to taki problem "urojony", bo w przeciętnej wielkości stronie, i tak nie ma to aż tak dużego znacznie. Gdybym pisał aplikację pod bardzo duże obciążenie to może bym się tym przejmował.
Go to the top of the page
+Quote Post
Cysiaczek
post
Post #65





Grupa: Moderatorzy
Postów: 4 465
Pomógł: 137
Dołączył: 26.03.2004
Skąd: Gorzów Wlkp.




Nie używałem Doctrine, ale Propela owszem i rzeczywiście - bardziej złożone zapytania wyglądają jeszcze bardziej zawile w propelu niż w gołym SQL. Trzeba jednak zauważyć dwie rzeczy
1. Bardzo złożone zapytania można również napisać ręcznie, a potem na podstawie wyniku wypełniać obiekty. Propel ma do tego wsparcie.
2. Złożone zapytania stanowią w większości systemów margines. Są to wszelkiego rodzaju wyszukiwania wg. złożonych kryteriów, którym nie podoła żadna forma obiektowa (w sensie zachowania prostoty).

Mitem jest, że Propel ma słabą wydajność. Relacje są ustawiane sztywno w wygenerowanych klasach, a wysyłane zapytania niczym sie nie różnią od normalnych zapytań. Późniejsze wypełnienie obiektów trwa tyle samo, ile by zajęło zrobienie tego ręcznie. Można jednie polemizować, czy operacje na 1000 rekordów należy wykonywać z pominięciem kreacji obiektów, czy nie.

Wadą, którą widzę w Doctrine jest to, że trzeba pisać kod php dla każdej tabeli. Nie ma żadnego generatora? Naprawdę bardzo fajnie koduje się strukturę z XML, czy nawet w YAML (o to nawet polubiłem). Już nie wspomnę i łatwiejszej edycji takiej struktury:)

Pozdrawiam.
Go to the top of the page
+Quote Post
athabus
post
Post #66





Grupa: Zarejestrowani
Postów: 898
Pomógł: 48
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


No niestety sama wydajnośc propel to nie do końca mit. Popatrz chociażby na ilość kodu klas generowanych przez propela. Samo załadowanie takiej ilości kodu to już niezłe obciążenie. Niektórych przypadkach propel też nie grzeszy wydajnością np. notka na blogu splatcha.

Ale tak jak pisałem wcześniej - to nie jest problem przy standardowej, dobrze napisanej stronie. Problemem może się natomiast okazać gdy na jednym hostingu próbujesz upchnąć 10-15 stron klientów itp., ale dla mnie to nie jest problem.
Go to the top of the page
+Quote Post
destroyerr
post
Post #67





Grupa: Zarejestrowani
Postów: 879
Pomógł: 189
Dołączył: 14.06.2006
Skąd: Bytom

Ostrzeżenie: (0%)
-----


Więc Doctrine ma możliwość definiowania schematu w pliku YAML (w przeciwieństwie do propela). Dodatkowo ma jeszcze wbudowany mechanizm migracji.
Tak jak pisał athabus, najwięcej czasu zajmuje napisanie tych prostych zapytań. Kiedyś sobie tesowałem, i wyszło mi, że szybciej (i krócej) jestem w stanie napisać takie zapytanie w Propelu niż w Doctrine.
Dodatkowo Propel (oczywiście w edytorze z podpowiadaniem składni) nie pozwala nam popełnić literówki, Doctrine jednak tak. Ale racją jest, że trudne zapytania w Propelu to duży problem.
Jeśli chodzi o wydajność to Propel 1.2 jest generalnie wolniejszy od Doctrine, ale już Propel 1.3 jest szybszy (oczywiście nikt nie musi zgadzać się z tym benchmarkiem.
Go to the top of the page
+Quote Post
splatch
post
Post #68





Grupa: Zarejestrowani
Postów: 487
Pomógł: 7
Dołączył: 7.01.2004
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Jeśli idzie o szybkość Propela w wersjach <= 1.2 to rzeczywiście nie było z nią najlepiej. Wszystko było spowodowane nienajlepszą konstrukcją "bindowania" z wyniku zapytania do obiektów. Zbędne iteracje i porównania robiły swoje, w wersji 1.3 całość wygląda znacznie lepiej.

Zapytania - Panowie zapominacie o najważniejszej zalecie Criterii. Można w bardzo prosty sposób stworzyć mechanizm tworzący na bazie wysłanego formularza kryteria do wyszukiwania i sortowania. Kiedyś taki mechanizm stworzyłem, wystarczyło stworzyć formularz a po stronie serwera powiedzieć które tabele będą używane. Mechanizm na podstawie nazw pól tworzył wyniki (porównania, mniejszy-większy, like, plus ograniczenia na relacje). Następnie warunki wędrowała do sesji (tablice o określonej strukturze), gdy ktoś wracał na stronę z wynikami trafiał dokładnie w to samo miejsce gdzie był np. przed edycją, bo stworzenie Criteria z tablicy było tylko formalnością. Z takim mechanizmem tworzenie widoków z listami zajmowało mi około 15 minut (formularze do wyszukiwania plus wyświetlanie wyników). Rezultatem tego było to, że później widoki (listy) mogła robić osoba, która miała pojęcie o html i smarty. (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Wykorzystajcie Criterię nie tylko do tworzenia zapytań, na prawdę warto zainwestować w jakiś automatyczny mechanizm jeśli jeszcze go nie macie. Parę komponentów do warstwy prezentacji, parę klas, kilka pętli a zysk czasowy na prawdę znaczny.
Go to the top of the page
+Quote Post
Sedziwoj
post
Post #69





Grupa: Zarejestrowani
Postów: 793
Pomógł: 32
Dołączył: 23.11.2006
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Do tego skomplikowane zapytania można oprzeć na widokach, a zdefiniować takie tabele w XML/YAML jako tylko do odczytu. Wtedy nie ma tego kodu po stronie PHP. @splatch dokładnie, wystarczy mały generatorek Criteria i mamy właściwie od ręki listy z filtrowaniem i stronicowaniem. Wystarczy powiedzieć jakie pole odpowiada któremu w bazie i jakie warunek porównania.

Ale tak jeszcze podkreślę, pamiętajcie że baza ma też coś więcej niż tabelki, więc wykorzystujcie te mechanizmy aby ułatwić sobie życie.
Go to the top of the page
+Quote Post
Strzałek
post
Post #70





Grupa: Przyjaciele php.pl
Postów: 384
Pomógł: 6
Dołączył: 11.09.2004
Skąd: Grodzisk Mazowiecki

Ostrzeżenie: (0%)
-----


Cytat
Wadą, którą widzę w Doctrine jest to, że trzeba pisać kod php dla każdej tabeli. Nie ma żadnego generatora? Naprawdę bardzo fajnie koduje się strukturę z XML, czy nawet w YAML (o to nawet polubiłem). Już nie wspomnę i łatwiejszej edycji takiej struktury:)


Oczywiście że jest. Można zdefiniować to w YAML, albo wygenerować sobie gotowe rekordy od razu z bazy danych.

Czy mówiąc o prostych zapytaniach macie na myśli to Doctrine User Manual::Magic Finders ?

Polecam poczytać dokumentacje. Doctrine oferuje nam naprawdę bardzoooo dużo.
Go to the top of the page
+Quote Post
Sedziwoj
post
Post #71





Grupa: Zarejestrowani
Postów: 793
Pomógł: 32
Dołączył: 23.11.2006
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


@Strzałek tylko powiedz w czym to jest lepsze od Propela? Bo jak już mówiłem to porównanie jest ważne, aby wykazać co jest lepsze. Bo ciągle jako porównanie bierzesz system bez ORM (źle się pisze bez klawiatury)
Go to the top of the page
+Quote Post
Cysiaczek
post
Post #72





Grupa: Moderatorzy
Postów: 4 465
Pomógł: 137
Dołączył: 26.03.2004
Skąd: Gorzów Wlkp.




Uh, jak mówiłem - nie używałem Doctrine. Jak jest generator, to ok (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) . W takim wypadku kwestia wyboru pomiędzy Propelem, a Doctrine, to jak wybór pomiędzy różnymi systemami szablonów ;] Jak będę miał czasa to zerknę na Doctrine i zobaczę co tak wychwalacie ;p

Pozdrawiam.
Go to the top of the page
+Quote Post
Sedziwoj
post
Post #73





Grupa: Zarejestrowani
Postów: 793
Pomógł: 32
Dołączył: 23.11.2006
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Cytat(Cysiaczek @ 15.03.2008, 20:26:32 ) *
Uh, jak mówiłem - nie używałem Doctrine. Jak jest generator, to ok (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) . W takim wypadku kwestia wyboru pomiędzy Propelem, a Doctrine, to jak wybór pomiędzy różnymi systemami szablonów ;] Jak będę miał czasa to zerknę na Doctrine i zobaczę co tak wychwalacie ;p


Cyba nie czytasz dokładnie, w Doctrine nie ma wsparcia do środowisk programistycznych, więc musisz pamiętać jakie masz pola w "tabelach"

(jeszcze raz rozbieram klawiaturę i czyszczę jeśli nie pomoze to kupuje nową, bo klawisze mi nie działają wszystkie )

EDIT:
No to będzie zakup nowej klawiatury :|

Ten post edytował Sedziwoj 15.03.2008, 21:46:32
Go to the top of the page
+Quote Post
Cysiaczek
post
Post #74





Grupa: Moderatorzy
Postów: 4 465
Pomógł: 137
Dołączył: 26.03.2004
Skąd: Gorzów Wlkp.




Oj tam (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Mi podpowiadanie składni w eclipse działa jak mu się podoba i to w momentach, gdy nie jest mi potrzebne, więc nie przekonuje mnie ten argument. Bardziej patrzę na funkcjonalność samej biblioteki.

Pozdrawiam.

p.s
Ja pisze z nowej klawiatury - dwa dni temu kupiłem (IMG:http://forum.php.pl/style_emoticons/default/snitch.gif)
Go to the top of the page
+Quote Post
Sedziwoj
post
Post #75





Grupa: Zarejestrowani
Postów: 793
Pomógł: 32
Dołączył: 23.11.2006
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Cytat(Cysiaczek @ 15.03.2008, 22:22:26 ) *
Oj tam (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Mi podpowiadanie składni w eclipse działa jak mu się podoba i to w momentach, gdy nie jest mi potrzebne, więc nie przekonuje mnie ten argument. Bardziej patrzę na funkcjonalność samej biblioteki.


Tylko że to jest duże funkcjonalne udogodnienie, a z podpowiadaniem to było na którymś blogu, do tego Ctrl+Spacja zawsze zadziała. (tylko aby obiekty propela były w projekcie)

Cytat
p.s
Ja pisze z nowej klawiatury - dwa dni temu kupiłem (IMG:http://forum.php.pl/style_emoticons/default/snitch.gif)


A pochwal się jaką? Bo ja nie mogę się zdecydować...

--- cysiaczek---
Wybacz, że tu, ale nie chce spamic
http://merlin.pl/Klawiatura-TRACER-Ibiza-T...208,556750.html
Go to the top of the page
+Quote Post

4 Stron V   1 2 3 > » 
Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 4.10.2025 - 13:00