Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> MVC - klasy modelu - pojedyncze obiekty i listy
marcini82
post
Post #1





Grupa: Zarejestrowani
Postów: 190
Pomógł: 1
Dołączył: 20.05.2005
Skąd: Poznań

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


Witam!

Pytanie dotyczy klas modelu w rozumieniu wzorca MVC, a ma zastosowanie chyba do prawie kazdego rodzaju danych przechowywanych w bazie. Otoz jesli mamy jakiekolwiek obiekty (uzytkownikow, ogloszenia, wiadomosci, itp.), to zazwyczaj istnieje potrzeba przeprowadzania operacji na pojedynczym obiekcie (dodanie, usuniecie, edycja itp.) oraz na grupie obiektow, spelniajacych okreslone kryteria (np. wyswietlenie listy uzytkownikow, ogloszen itp.). Jaka tworzycie tutaj strukture klas?
Czy robicie dwie klasy, z ktorych jedna reprezentuje pojedynczy obiekt a druga liste takich obiektow (np. Uzytkownik i ListaUzytkownikow)? A moze jedna klasa (np. Uzytkownik) posiada metody obslugujace obie mozliwosci, np. pobierz($id) dla pojedynczego obiektu i pobierzListe() dla calej listy obiektow? A moze jeszcze inaczej?

EDIT: Wlasciwie to ten temat powinienem dac do PHP > Programowanie obiektowe. Moze moderator zechcialby go przeniesc?

Ten post edytował marcini82 3.03.2007, 14:58:48
Go to the top of the page
+Quote Post
strife
post
Post #2





Grupa: Przyjaciele php.pl
Postów: 2 605
Pomógł: 96
Dołączył: 22.10.2004
Skąd: UK

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


Przenoszę do PHP > Programowanie obiektowe


--------------------
Go to the top of the page
+Quote Post
Strzałek
post
Post #3





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

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


Zobacz sobie model w Cake, poczytaj o ActiveRecord.

Ja mam klasę NewsContainer, z metodami findById, findByTitle, findAll etc.


--------------------
Go to the top of the page
+Quote Post
Athlan
post
Post #4





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Strzałek dobrze prawi imho... model users powinien obsługiwać metody takie jak findAll, get($mId, $bByName = false), setEmail(), setParams( jakies dane usera ) itp itd dotyczącego usera. Mogę zarzucić przykład z mojego modelu obsługującego filmiki w bazie danych (skomny, ale przedstawi działanie):

  1. <?php
  2.  
  3. class movies_Vmodel extends Vmodel
  4. {
  5. public function getLastModified($iTime)
  6. {
  7. $oDb = $this->getSource();
  8.  
  9. $oDb->setOrder("movie_time_edit ASC");
  10. $oDb->setWhere("movie_time_edit > " . (time() - $iTime));
  11.  
  12. $rResult = $oDb->dbSelect('movies', true, array('users' => 'movie_owner = user_id'));
  13.  
  14. $oDb->clear();
  15.  
  16. return $oDb->fetchAll($rResult);
  17. }
  18.  
  19. function getUserMovies($iUser)
  20. {
  21. $oDb = $this->getSource();
  22.  
  23. $oDb->setWhere("movie_owner = " . (int)$iUser);
  24.  
  25. $rResult = $oDb->dbSelect('movies', true);
  26.  
  27. $oDb->clear();
  28.  
  29. return $oDb->fetchAll($rResult);
  30. }
  31.  
  32. function setMovie($iUser, $sDescription, $sCode)
  33. {
  34. $oDb = $this->getSource();
  35.  
  36. $oDb->movie_owner = $iUser;
  37. $oDb->movie_text = $sDescription;
  38. $oDb->movie_code = $sCode;
  39. $oDb->movie_time = time();
  40. $oDb->movie_time_edit = time();
  41.  
  42. $rResult = $oDb->dbInsert('movies');
  43.  
  44. if($rResult)
  45. $oDb->Execute("UPDATE users SET user_count_movies = user_count_movies + 1 WHERE user_id = " . $iUser);
  46.  
  47. $oDb->clear();
  48. }
  49.  
  50. function getMovie($iId)
  51. {
  52. $oDb = $this->getSource();
  53.  
  54. $oDb->setWhere("movie_id = " . (int)$iId);
  55.  
  56. $rResult = $oDb->dbSelect('movies', true, array('users' => 'movie_owner = user_id'));
  57.  
  58. $oDb->clear();
  59.  
  60. return $oDb->fetch(1, $rResult);
  61. }
  62.  
  63. function unMovie($iId, $aData)
  64. {
  65. $oDb = $this->getSource();
  66.  
  67. $oDb->setWhere("movie_id = " . (int)$iId);
  68.  
  69. $rResult = $oDb->dbDelete('movies');
  70.  
  71. $oDb->clear();
  72.  
  73. $oDb->Execute("UPDATE users SET user_count_movies = user_count_movies - 1 WHERE user_id = " . $aData['movie_owner']);
  74.  
  75. return $rResult;
  76. }
  77.  
  78. function setMovieDesc($iId, $sDesc)
  79. {
  80. $oDb = $this->getSource();
  81.  
  82. $oDb->setWhere("movie_id = " . (int)$iId);
  83. $oDb->movie_text = substr($sDesc, 0, 40);
  84. $oDb->movie_time_edit = time();
  85.  
  86. $rResult = $oDb->dbUpdate('movies');
  87.  
  88. $oDb->clear();
  89.  
  90. return $rResult;
  91. }
  92. }
  93.  
  94. ?>


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
Strzałek
post
Post #5





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

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


Trochę mało wygodnie to masz. Przy tabelach które nie potrzebują joinów u mnie wystarczy

  1. <?php
  2.  
  3.  class NewsContainer extends DatabaseMapper {
  4.  public $table = "news";
  5.  }
  6.  
  7. ?>


I juz mam wszystko czego potrzebuję

  1. <?php
  2.  
  3. $news = new NewsContainer();
  4.  
  5. $news -> findAll();
  6. //lub
  7. $fields = array('id', 'title', 'time', 'comments', 'intro');
  8. $criteria = array('sort_by' => 'id', 'sort_type' => 'DESC', 'limit' => '10');
  9.  
  10. $news -> findAll($fields, $criteria);
  11.  
  12.  
  13. $news -> findById($id);
  14. $news -> findByTitle('Tytuł newsa');
  15.  
  16. $news -> deleteById($id);
  17.  
  18. $nowyNews = array('title' => 'Super tutuł', 'text' => 'tresc', 'time' => time());
  19.  
  20. $news -> save($nowyNews);
  21.  
  22. ?>


Proste prawda smile.gif ?

Do każdej rzeczy będziesz teraz pisał findAll, findBy(.*), ja u siebie mam abstrakcyjna klasę modelu, która mam podstawowe metody - find, save, update, delete + dodatkowo, __call które obsługuje findByTitle odpalając metodę find z odpowiednimi argumentami. Taki sposobem powstał mały DatabaseMapper. Bez żadnych wodotrysków i zapytań z joinami. Jeżeli potrzebuję do NewsContainer'a łaczyć tabele, dopisuje sobie wtedy metodę i recznie piszę zapytanie.

No chyba że mam tego więcej. Wtedy mamy Propel lub PHP Doctrine


--------------------
Go to the top of the page
+Quote Post
Athlan
post
Post #6





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


@Strzałek, owszem, przyznam się, że obsługa bazy danych to kicha u mnie tongue.gif mi tam wygodnie jest, ale w przykladze chodzilo głownie o to, aby pokazać możliwości modelu (filmy to filmy itp).

Co do tej obsługi... w Rapide budowana jest całkiem nowa już smile.gif


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
marcini82
post
Post #7





Grupa: Zarejestrowani
Postów: 190
Pomógł: 1
Dołączył: 20.05.2005
Skąd: Poznań

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


Dzieki za odpowiedzi. Jak sobie czytam o ActiveRecord to widze, ze to jest mniej wiecej to, co od jakiegos czasu zazwyczaj stosowalem, nie nazywajac tego w ten sposob smile.gif

@Strzalek - ciekawa koncepcja tego DatabaseMapper. Wlasnie mysle, czy da sie stworzyc cos tak uniwersalnego dla projektu nad ktorym siedze :-)

Ten post edytował marcini82 5.03.2007, 07:20:53
Go to the top of the page
+Quote Post
Turgon
post
Post #8





Grupa: Zarejestrowani
Postów: 800
Pomógł: 0
Dołączył: 26.11.2005
Skąd: Nowy Sącz

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


Strzałek: Mam kilka wątpliwości. Otóż też napisałem takiego podobnego DatabaseMappera, który ładuje na podstawie takiej:
load(fieldName,fieldValue);
I tak sie zastanawiam, czy to ma sens w takiej formie ? Bo wtedy Obiekt, który należy do grupy TurActiveRecord i jest odpalany przez fabrykę. Ma tą zaletę, że nie trzeba się bawić w rozdział mapperów dla baz?


--------------------
Jah Music Is On My Mind !
Go to the top of the page
+Quote Post
Strzałek
post
Post #9





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

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


Nie wiem o co Ci chodzi. Za dużo filozofii i sztuki dla sztuki widzę u Ciebie. Mam Controller w którym jak potrzebuję to tworzę sobie nowy obiekt np. NewsContainer. Jak nie potrzeba to nie tworzę i tyle.


--------------------
Go to the top of the page
+Quote Post
Turgon
post
Post #10





Grupa: Zarejestrowani
Postów: 800
Pomógł: 0
Dołączył: 26.11.2005
Skąd: Nowy Sącz

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


O może tak. Mam taki problem, że u mnie Database Mapper działa tylko dla jednego obiektu. Jak proponujesz to przerobić by pracowało z wieloma rekordami? Jak zrobić hasOne i hasMany ? Tylko tyle mi potrzeba smile.gif?


--------------------
Jah Music Is On My Mind !
Go to the top of the page
+Quote Post
Strzałek
post
Post #11





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

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


Aaaa, hehe. Napisałem wyżej że ominąłem relacje. Można je napisać i nie jest to wcale trudne. Po prostu przy find(.*) musisz dodatkowo obsłużyć relacje. Dodajesz właściwości $hasMany, $hasOne np.:

  1. <?php
  2.  class NewsContainer extends DatabaseMapper {
  3.  public $table = 'news';
  4.  public $hasOne = 'author';
  5.  }
  6. ?>


Dalej automatycznie się wszystko dzieje.


--------------------
Go to the top of the page
+Quote Post
Turgon
post
Post #12





Grupa: Zarejestrowani
Postów: 800
Pomógł: 0
Dołączył: 26.11.2005
Skąd: Nowy Sącz

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


Eeee... Poprosiłbym jakieś dokładniejsze przykłady ? Dla mnie trzeba łopatologicznie. Najchętniej bym poczytał coś w stylu artykułów o DBObject Hwaka smile.gif


--------------------
Jah Music Is On My Mind !
Go to the top of the page
+Quote Post
marcini82
post
Post #13





Grupa: Zarejestrowani
Postów: 190
Pomógł: 1
Dołączył: 20.05.2005
Skąd: Poznań

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


Nie do konca Turgon rozumiem, w czym tkwi twoj problem, i co ma oznaczac to $hasOne i $hasMany... Jesli NewsContainer ma okreslona tabele news to w DatabaseMapper budujesz uniwersalne zapytanie w oparciu o te tabele i dostajesz zestaw rekordow...
Moze gdybys wytlumaczyl tak lopatologicznie, na jakims przykladzie, to ktos bylby w stanie ci pomoc.
Go to the top of the page
+Quote Post
Strzałek
post
Post #14





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

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


Chodzi o relacje. Tabele buduje się relacyjnie. Np.

News
id
title
text
author

Comments
id
news_id
text

Users
id
login
pass

I w tabeli news trzymamy w polu author, numer id usera, natomiast w comments trzymamy komentarze gdzie w news id znajduje się id newsa do którego dodano komentarz. Żeby coś takiego uzyskać są potrzebne relacje has.... To tak w telegraficznym skrócie. Ale to już wyższa szkoła jazdy. W swoim czasie się dowiesz o co chodzi.


--------------------
Go to the top of the page
+Quote Post
marcini82
post
Post #15





Grupa: Zarejestrowani
Postów: 190
Pomógł: 1
Dołączył: 20.05.2005
Skąd: Poznań

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


Cytat
Chodzi o relacje.

A no to w takim razie ja bym zrobil cos takiego:
  1. <?php
  2. class NewsContainer extends DatabaseMapper {
  3.  public $table = 'news';
  4.  public $joins = Array('author' => 'Users.id');
  5.  }
  6. ?>

Jak mamy w $joins okreslone kolumny na ktorych robimy zlaczenia to mozemy to wykorzystac w uniwersalnej metodzie DatabaseMappera. A jak trzeba cos bardziej wyrafinowanego wyciagnac niz proste zlaczenie 2-3 tabel to lepiej w NewsContainer nadpisac metode z DatabaseMapper i wklepac nowe zapytanie.
Wlasciwie to ja bym tego nie nazwal wyzsza szkola jazdy bo to raczej podstawy relacyjnych baz danych snitch.gif
Napisanie dobrej i uniwersalnej struktury klas to juz co innego...

Sposobu praktycznego wykorzystania tego $hasOne nadal nie zalapalem, ale to moze nie jest takie istotne...

Ten post edytował marcini82 11.03.2007, 12:24:32
Go to the top of the page
+Quote Post

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: 22.08.2025 - 04:47