Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [PHP]podział na klasy
perhydrol
post
Post #1





Grupa: Zarejestrowani
Postów: 50
Pomógł: 0
Dołączył: 11.12.2006

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


Witam,

od jakiegoś czasu eksperymentuję z obiektowym PHP, jednak moje strukturalne myślenie skutecznie mi to utrudnia.
Tylko proszę nie odsyłajcie do przeszukiwania tematów jak wielokrotnie twierdzicie iż temat był poruszany tysiące razy,
ja jednak szukając odpowiedzi w postach już istniejących na tym forum nie znalazłem satysfakcjonującej odpowiedzi.

Mam prośbę, czy mógł by ktoś mi wypisać na przykładzie sklepu internetowego podział na klasy, oraz zakwalifikować je do odpowiednich części:
Model, View, Controller

Coś w stylu listingu klas, i nie jest to z mojej strony wyręczanie się Wami, a jedynie chciał bym dostrzec jak szczegółowo należy podejść do podziału danej dziedziny sklepu internetowego na klasy. Dzięki przypisaniu ich do odpowiednich części MVC, myślę że będę mógł szybciej i lepiej zrozumieć to z czym się borykam. Dodam może że do UML-a używam "NetBeans IDE 6.7.1"

a interesujące mnie rozwiązanie to coś w stylu:

  1. class DB_Connect // klasa inicjująca połączenie z baza danych
  2. class DB_View // klasa zapytań do bazy danych
  3. .... // tu kolejne pytanie czy jest sens przechowywać wszystkie zapytania do bazy danych, np SELECT ... w jednym pliku?
  4. .... // no i jeszcze jak by mógł mi ktoś zaznaczyć która klasa do jakiej części modelu MVC się zalicza


Ten post edytował nospor 14.10.2009, 23:08:53
Go to the top of the page
+Quote Post
2 Stron V   1 2 >  
Start new topic
Odpowiedzi (1 - 19)
thek
post
Post #2





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




MVC robią dokładnie to co sugeruje nazwa. Różnica polega na tym, że pewne klasy nie będą miały wszystkich trzech. Przykład? Klasa połączenia z bazą danych. Zauważ, że ona nie musi mieć widoku, gdyż nigdzie nie prezentujesz danych tylko przepychasz je do innych klas. Myśl własnie w ten sposób. Jeśli chcesz jakieś dane uwidaczniać, to projektuj do tego widok. Chcesz wyciągać dane? Pomyśl o modelu. Gdy trzeba nad tym wszystkim odpowiednio popracować to nie obejdzie się bez kontrolera.. Jak więc widzisz kontroler jest w zasadzie zawsze, bo musi kierować poczynaniami i przepływem danych. Czasem niepotrzebny jest klasie model, jeśli nie operujesz na danych pobieranych z zewnątrz (baza czy pliki).
Ja osobiście robię tak, że mam zawsze główny kontroler dziedziczący po jakimś template i do niego wrzucam widoki. Jeśli któryś z widoków pobiera dane to ma on dostęp albo do dedykowanego mu modelu, albo korzysta z pewnego globalnego modelu. Jeśli zaś ten widok ma podwidoki, to mają one zazwyczaj własne kontrolery i własne widoki. Całość układa się wtedy w swego rodzaju drzewko zależności. W takiej sytuacji do widoku głównego przez główny kontroler są wysyłane mniejsze widoki korzystające z własnych kontrolerów, widoków i modeli (choć mogą korzystać z pewnego głównego modelu dla danych lub nie korzystać z modeli wcale). By je odróżnić nadaję im odpowiednie nazewnictwo. Ciekawostką dla początkujących jest choćby klasa autoryzacji. Zauważ, że nigdzie ona nie prezentuje danych, czyli jest klasą bez widoku. Ma model by pobrać dane ze źródła, Kontroler dla przepływu i obróbki danych i nic więcej nie trzeba do szczęścia.


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
perhydrol
post
Post #3





Grupa: Zarejestrowani
Postów: 50
Pomógł: 0
Dołączył: 11.12.2006

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


dzięki wielkie "thek" za zrozumiały opis i wytłumaczenie,
prosił bym jednak w dalszym ciągu o rozpisanie dziedziny sklepu internetowego na klasy(listy nazw klas na jakie należy podzielić aplikację), tak aby mieć punkt odniesienia jak szczegółowo do tego podchodzić, mile widziana jakaś przykładowa, sensowna konwencja nazewnicza klas, metod...

-pozdrawiam
--------------------------------------------------------------------------------------------------------------

może inaczej zapytam, pomoże ktoś przy wydzieleniu klas?
powiedzmy tak poglądowo (nazewnictwo w języku PL, wyłącznie dla zobrazowania przykładu)
np:
  1. class Uzytkownik {
  2. //:: pytanie czy rozbijać na dwie f-cje, czy w f-cji rejestracja umieścić tę część
  3. function walidacjaDanychRejestracji{
  4. ..........
  5. }
  6. //::
  7. function rejestracja(){
  8. ..........
  9. }
  10. //::
  11. function logowanie(){
  12. ..........
  13. }
  14. //::
  15. function wylogowanie{
  16. ..........
  17. }
  18. //:: f-cja pozwalająca na wygenerowanie przez system, nowego hasła dla użytkownika
  19. function rzadanieNowegoHasla{
  20. ..........
  21. }
  22. //:: f-cja umożliwiająca wprowadzenie nowego hasła przez użytkownika
  23. function ustawNoweHaslo{
  24. ..........
  25. }
  26. //:: f-cja umożliwiająca zmianę wybranych danych użytkownika
  27. function zmienDaneUzytkownika{
  28. ..........
  29. }
  30. //::
  31. function pokazPrzyslugujacyRabat{
  32. ..........
  33. }
  34.  
  35. }


wiem również że w tym przykładzie wymieszałem części modelu M V C, ale interesuje mnie jak podejść do sprawy podziału wypisanych funkcji na klasy, prosił bym kogoś o pogrupowanie oraz podział na klasy(z małym komentarzem dlaczego), interesuje mnie jak Wy to robicie.

-pozdrawiam

Ten post edytował perhydrol 14.10.2009, 21:15:45
Go to the top of the page
+Quote Post
jmail
post
Post #4





Grupa: Zarejestrowani
Postów: 352
Pomógł: 53
Dołączył: 10.08.2009

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


hmmmmm. zdaje mi się czy pomyliliśmy pojęcia MVC? winksmiley.jpg

Za wiki

Cytat
Użycie MVC można przedstawić na przykładzie aplikacji bazodanowej. Wtedy:

modelem jest encja (lub ich zbiór) z bazy danych,
widokiem tabela danych pokazywana użytkownikowi, a
kontrolerem przyciski do manipulacji.
Kontroler jest odpowiedzialny za odczyt danych z bazy danych (utworzenie modelu) i przekazanie ich do warstwy widoku (interfejsu użytkownika). Gdy użytkownik wybierze pokaż kolejne, wtedy odwołanie jest przekazywane do kontrolera, który ponownie pobiera dane i przekazuje do widoku tą samą drogą.


Załóżmy że napisaliśmy sobie jakąś klasę do łączenia i pobierania danych z bazy (nie widzę sensu rozbijać tego na dwie klasy) i mamy drugą klasę do wyświetlania template'ów wiadomo, że zazwyczaj jedno i drugie będzie wykorzystywane na stronach. I teraz tak klasa do łączenia będzie naszym modelem (właściwie powłoką do oglądania tych danych) automat do parsowania templatek (na przykład Smarty) będzie widokiem a to co się dzieje w naszych funkcjach to kontroler.

I to aplikacja dzieli się na taki podział a nie pojedyncze klasy winksmiley.jpg

Czy się pomyliłem ? biggrin.gif
Go to the top of the page
+Quote Post
perhydrol
post
Post #5





Grupa: Zarejestrowani
Postów: 50
Pomógł: 0
Dołączył: 11.12.2006

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


wiec tak dla sprostowania, pojęć nie pomyliłem, może w jednym miejscu źle sformułowałem zdanie, ale tak jak pisze w pierwszym poście, chcę przejść na obiektowe programowanie aplikacji, w odniesieniu do "wzorca" ? MVC
odnośnie MVC, "thek" udzielił mi wyczerpującej odpowiedzi, za co dziękuję.
Na przykładzie Zend Framework jeśli by ktoś potrzebował to myślę że warto przeczytać:
http://www.heavymind.net/zend-framework-tutorial/#100

natomiast moje ostatnie pytanie, a może raczej prośba o pomoc dotyczy podziału danej dziedziny w założeniach sklepu internetowego, czy tez na przykładzie funkcji odnoszących się do UŻYTKOWNIKA, jak ma to miejsce w ostatnim poście na klasy.

Ponieważ powtarzam, mam problem z odpowiednim wydzieleniem i zakwalifikowaniem pewnych metod do poszczególnych klas(z małym komentarzem dlaczego tak), więc poprosiłem o przedstawienie propozycji przez kogoś bardziej doświadczonego w kodowaniu Obiektowym, abym mógł sobie znaleźć jakąś analogie na konkretnym przykładzie.
Proszę nie przytaczajcie przykładu klasy obsługującej bazę danych(wiem że to dobry przykład) ponieważ ona ma sama w sobie bardzo logiczny podział, proszę o pomoc przy przykładzie który ja zamieściłem smile.gif


-dzięki za pomoc smile.gif

Ten post edytował perhydrol 14.10.2009, 23:05:26
Go to the top of the page
+Quote Post
thek
post
Post #6





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Zauważ, że przykładową klasą Użytkownik mieszasz już nieco strukturę. Są w niej bowiem funkcje z różnych "warstw". I tak:
Walidacja -> Model
Rejestracja -> Model
Logowanie -> Kontroler
Wylogowanie -> Kontroler
Nowe hasło -> Model
Zmień hasło -> Model
Zmień dane -> Model
Pokaż rabat -> Widok
Problem w tym, że nawet to jest w sposób, który nie do końca jest prawidłowy. Dlaczego?Bo część z tych operacji jest wykonywana poprzez więcej niż 1 "warstwę". Przykładowo Pokaż rabat jest tak naprawdę Widokiem, ale musi posłużyć się metodami Modelu by uzyskać te dane. Tak naprawdę więc nie ma w klasie usera żadnego widoku. Jest za to jeden wielki model danych użytkownika, którego metodami posługują się inne klasy. Nie ma czegoś takiego jak logowanie czy wylogowanie, bo to kontroler zupełnie innej klasy. Tak naprawdę w klasie użytkownik masz metody służące do jego dodania, usunięcia, wyciągnięcia pewnych lub wszystkich danych bądź ich zmiany. Rabat jest tutaj czymś zupełnie obcym i można powiedzieć, że jest osobną klasą. Walidacja nie jest osobną metodą, gdyż musi być implementowana w każdej z metod odpowiedzialnych za edycję. Nie napiszesz nigdy zunifikowanej wersji musiałbyś dla każdego typu pola pisać osobną metodę walidacji go. Inaczej bowiem waliduje się adres e-mail a inaczej adres www lub konkretne pole liczbowe czy znakowe. Poza tym czasem jakieś pola przy edycji w określonych przypadkach walidujesz, a inne nie, gdyż nie są nawet wypełniane. Jak wyobrażasz sobie choćby metodę walidacji z jedną metodą gdy raz posyłamy ją tylko do zmiany hasła, a innym razem do dodawania usera?
Najprościej rzecz ujmując istnieją jakby dwie klasy użytkownik. Jedna to kontroler, druga to model. User_Kontroler może wywołać metodę rejestracja, która zainicjuje User_Model łącząc ją ze źródłem danych, zwaliduje dane i gdy zwróci błąd (banalne hasło, login już istnieje, nieprawidłowe dane w formularzu lub nieprawidłowy ich format) poinformuje User_Kontroler o tym. Jeśli zaś wszystko ok to doda do źródła danych i zrobi ewentualnie coś jeszcze.

Sklep internetowy podziel na role wpierw i pomyśl co Ci potrzebne. Na pewno użytkownik, na pewno produkt i koszyk To minimum, ale w zależności od stopnia komplikacji rozszerzy się to zapewne o inne. Nie ma jasnej i gotowej odpowiedzi o podział, gdyż niemal każdy inaczej widzi go, choć teoretycznie każdy korzysta z tej samej definicji winksmiley.jpg


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
jmail
post
Post #7





Grupa: Zarejestrowani
Postów: 352
Pomógł: 53
Dołączył: 10.08.2009

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


Cytat(thek @ 15.10.2009, 09:24:26 ) *
Zauważ, że przykładową klasą Użytkownik mieszasz już nieco strukturę. Są w niej bowiem funkcje z różnych "warstw". I tak:
Walidacja -> Model
Rejestracja -> Model
Logowanie -> Kontroler
Wylogowanie -> Kontroler
Nowe hasło -> Model
Zmień hasło -> Model
Zmień dane -> Model
Pokaż rabat -> Widok
Problem w tym, że nawet to jest w sposób, który nie do końca jest prawidłowy. Dlaczego?Bo część z tych operacji jest wykonywana poprzez więcej niż 1 "warstwę". Przykładowo Pokaż rabat jest tak naprawdę Widokiem, ale musi posłużyć się metodami Modelu by uzyskać te dane. Tak naprawdę więc nie ma w klasie usera żadnego widoku. Jest za to jeden wielki model danych użytkownika, którego metodami posługują się inne klasy. Nie ma czegoś takiego jak logowanie czy wylogowanie, bo to kontroler zupełnie innej klasy. Tak naprawdę w klasie użytkownik masz metody służące do jego dodania, usunięcia, wyciągnięcia pewnych lub wszystkich danych bądź ich zmiany. Rabat jest tutaj czymś zupełnie obcym i można powiedzieć, że jest osobną klasą. Walidacja nie jest osobną metodą, gdyż musi być implementowana w każdej z metod odpowiedzialnych za edycję. Nie napiszesz nigdy zunifikowanej wersji musiałbyś dla każdego typu pola pisać osobną metodę walidacji go. Inaczej bowiem waliduje się adres e-mail a inaczej adres www lub konkretne pole liczbowe czy znakowe. Poza tym czasem jakieś pola przy edycji w określonych przypadkach walidujesz, a inne nie, gdyż nie są nawet wypełniane. Jak wyobrażasz sobie choćby metodę walidacji z jedną metodą gdy raz posyłamy ją tylko do zmiany hasła, a innym razem do dodawania usera?
Najprościej rzecz ujmując istnieją jakby dwie klasy użytkownik. Jedna to kontroler, druga to model. User_Kontroler może wywołać metodę rejestracja, która zainicjuje User_Model łącząc ją ze źródłem danych, zwaliduje dane i gdy zwróci błąd (banalne hasło, login już istnieje, nieprawidłowe dane w formularzu lub nieprawidłowy ich format) poinformuje User_Kontroler o tym. Jeśli zaś wszystko ok to doda do źródła danych i zrobi ewentualnie coś jeszcze.

Sklep internetowy podziel na role wpierw i pomyśl co Ci potrzebne. Na pewno użytkownik, na pewno produkt i koszyk To minimum, ale w zależności od stopnia komplikacji rozszerzy się to zapewne o inne. Nie ma jasnej i gotowej odpowiedzi o podział, gdyż niemal każdy inaczej widzi go, choć teoretycznie każdy korzysta z tej samej definicji winksmiley.jpg



Bo mnie zaraz coś trafi. Nie myl koledze.

Walidacja -> Model - bzdura - kontroler
Rejestracja -> Model - bzdura - kontroler
Logowanie -> Kontroler - no wreszcie coś rozsądnego
Wylogowanie -> Kontroler - i znowu coś rozsądnego
Nowe hasło -> Model - bzdura! - kontroler
Zmień hasło -> Model - bzdura! - kontroler
Zmień dane -> Model - bzdura! - kontroler
Pokaż rabat -> Widok - bzdura! - kontroler

Nie myl pojęć

Aplikacja ma być podzielona na warstwy a nie klasy. Poza tym są klasy do łączenia się z bazą danych i do wykonywania zapytań. Więc to one są Model'em. Widok to będzie mechanizm parsujący templatkę, a wszystko co się między nimi odbywa jest kontrolerem. Stworzenie zapytania (stringa) może być częścią kontrolera albo modelu - Twoja sprawa jak to zrobisz. Ale już walidacja w php (czy wszystkie dane zostały wpisane) jest czystym kontrolerem.

Podział na klasy w sklepie (według mnie):

klasa Modelu - do łączenia z bazą, tworzenia zapytań
klasa Widoku - na przykład smarty
klasa użytkownika (z wszelkimi niezbędnymi metodami)
klasa koszyka
klasa zamówienia
klasa modułu (za chwilę to wyjaśnię)
klasa dostawy (wprowadzanie świeżego towaru do sklepu)

To chyba wszystko co Ci jest potrzebne

Co do modułu. Na stronę moim zdaniem trzeba spojrzeć jak na wielki moduł, w którym są ładowane różne inne moduły.

Może obrazek tongue.gif



Każdy z zaznaczonych na obrazku modułów składa się dokładnie z tego samego

1. tworzysz moduł
2. napełniasz go danymi
3. parsujesz template


Teraz załóżmy że budujesz klasę w PHP która będzie się nazywać modul

  1.  
  2. <?php
  3.  
  4. class modul{
  5. public $smarty = '';
  6. public $module = '';
  7. public $page = '';
  8. public $top = '';
  9. public $bottom = '';
  10. public $conn = null;
  11. public $queries = null;
  12. public $tables = null;
  13. public $parameters = null;
  14.  
  15. public function __construct($module, $connections, $top = 1, $bottom = 1){
  16. //tu coś się dzieje
  17. $this->CreateConnections($connections);
  18. $this->ReadQueries();
  19. }
  20.  
  21. public function getPage(){
  22. $this->page = $this->smarty->fetch($this->module.'.tpl');
  23. }
  24.  
  25. public function CreateConnections($connections){
  26. //tworzy połączenia do baz danych
  27. }
  28.  
  29. public function ReadQueries(){
  30. //zaczytuje zapytania do wykonania w module
  31. }
  32.  
  33. public function constructQuery($i, $j){
  34. //to jest niezbędne do obsługi silnika DB
  35. }
  36.  
  37. public function executeQuery($i){
  38. //wykonuje konkretne zapytanie
  39. }
  40.  
  41. public function assignVar($name = '', $value = ''){
  42. $this->smarty->assign($name, $value);
  43. }
  44.  
  45. public function display(){
  46. echo $this->top.$this->page.$this->bottom;
  47. }
  48. }
  49. ?>
  50.  
  51.  


to jest przykład z modelu MVC

teraz tak. Każdy z modułów na stronie może robić dokładnie to samo jak już pisałem wcześniej.

Założmy taki newsletter

  1.  
  2. <?php
  3. class Newsletter extends modul{
  4. public function __construct($connections){
  5. parent::contruct('newsletter', $connections, 0, 0);
  6. //dodałem zera do konstrukcji rodzica bo one akurat wskazują czy nagłowek i stopka mają być dodane do modułu. to jest fragment strony więc nie potrzeba nam ani nagłówka ani stopki
  7. //newsletter zawsze będzie się wyświetlał tak samo, więc gdzie to wywoływać parsowanie? gdzie indziej? a po co? biggrin.gif
  8. $this->getPage();
  9. //jeszcze ważna rzecz trzeba pamiętać, ze ktoś może się chcieć dopisać
  10. if(isset($_POST['save']) && $_POST['save'] == 'newsletter'){
  11. $this->addToNewsleetter();
  12. }
  13. }
  14.  
  15. public function addToNewsletter(){
  16. //tu dopisujemy do newslettera osoby :)
  17. }
  18. }
  19. ?>
  20.  


a teraz sama strona - założmy index w którym załóżmy że wystepuje newsletter

  1.  
  2. <?php
  3.  
  4. class index extends module{
  5. public function __construct($connections){
  6. parent::contruct('index', $connections);
  7. //jak widać teraz nagłowek i stopka zostaną do strony dołączone ;)
  8.  
  9. //tu oczywiście inne rzeczy mogą się jeszcze dziać
  10. }
  11. }
  12.  
  13. ?>
  14.  


I na końcu sklejenie tego wszystkiego w całość

  1.  
  2. <?php
  3. require_once('includes/application.php'); //w tym pliku trzymam wszystkie dane niezbędne do połączenia i na przykład funkcję __autoload
  4. $index = new index($connections);
  5. $newsletter = new Newsletter($connections);
  6. $index->assignVar('newsletter', $newsletter->page);
  7. $index->getPage();
  8. $index->display();
  9. ?>
  10.  


i templatka (index.tpl)

  1. <div>
  2. {newsletter}
  3. </div


Mam nadzieję, że rozumiesz o co mi chodzi ^^
Go to the top of the page
+Quote Post
fenix.robi
post
Post #8





Grupa: Zarejestrowani
Postów: 97
Pomógł: 7
Dołączył: 24.06.2008

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


Ja proponuje skorzystać z fameworka CAKE'a, który jest oparty o MVC, i przerobić pierwszy tutorial o blogu, łatwo na nim sie nauczyc co za co odpowiada, (btw Walidacja jest w modelu), jak Ci się nie spodoba to nie będziesz używał,a le chociaż zasmakujesz tematu.
Go to the top of the page
+Quote Post
thek
post
Post #9





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




To może jmail wyjaśnię dlaczego podałem taki a nie inny podział dla jasności. Jadę na Kohana 2.X co implikuje pewne podejście do programu. Tam jest, jak zapewne wiesz, podział na zasadzie klasy modeli, kontrolerów i widoków osobno. Dla zachowania przenośności i skalowalności klasy mam niejako 3 wersje w dużej ilości wypadków: Nazwa_klasy_Controller, Nazwa_klasy_Model, Nazwa_klasy_View, gdyż traktuję ją nieraz jako osobny "panel", który mogę w łatwy sposób wyrzucić, zmienić.
I tak wiele z tego co zostało wymienione jest tak naprawdę tylko wywołaniem w kontrolerze odpowiednich metod Modelu. Zauważ, że w takim wypadku niemal wszystko sprowadziłeś do poziomu kontrolera. A powiedz mi czy Kontroler tak naprawdę wie czy w bazie danych można zarejestrować kogoś? Nie wie. Musisz w kontrolerze zapytać model czy taki user już istnieje i dopiero on Ci odpowie zgodą lub nie na operację. W kontrolerze więc wywołuję metodę user_model->nowy_user($_POST) i oczekuję na efekty. To na poziomie modelu przebiegnie walidacja danych, a ja jedynie zwrot dostanę czy operacja przebiegła prawidłowo czy nie( w pewnej formie przeze mnie wybranej) i ewentualnie od niej podejmę jakieś działanie. Ujmując to inaczej... Napisałem gdzie tak naprawdę dzieje się podstawowa część danej opcji. Bo czy napisanie w kontrolerze funkcji do zmiany hasła w stylu
public function zmien_haslo($user, $nowe) {
(...)
}
jest inne od tego samego w modelu? To model ma się zająć operacjami na danych a nie kontroler. Ja co najwyżej mogę z kontrolera modelowi to zlecić i zinterpretować wynik otrzymany. Myślę, że rozumiesz moje podejście. Kontroler sterować ma przepływem danych, a nie na nich operować (walidować, obrabiać). Z takim podejściem na model zrzuciłeś jedynie wykonanie zapytań do źródła danych, ale całość operacji masz w kontrolerze. Odnosisz się do niego jedynie by pobrać lub wysłać dane.
Login i logout są w kontrolerze, gdyż bezpośrednio tyczą klasy User i stanu w jakim się znajduje na portalu poprzez operacje na sesji użytkownika. Koszyk zbiera informacje o wyborze produktów na stronach. Pokaz_rabat to odwołanie do wysłanie do widoku danych z jakiegoś modelu. Realizuje to kontroler tak jak napisałeś, ale to na widoku spoczywa prezentacja danych w odpowiedniej formie. Stąd tak przyporządkowałem. Nie na zasadzie gdzie programuję daną funkcję, ale gdzie jest jej meritum, na jaki element mamy zwrócić uwagę w szczególności. Wracając do Pokaż_rabat to czy nie jest to po prostu(skrótowo, bo powinienm jeszcze sprawdzić wyjście funkcji pokaz_rabaty(parametry) ) ):
  1. User_widok_rabaty->dane = user_model->pokaż_rabaty(parametry);
  2. User_widok_rabaty->display();
Powiedz mi więc gdzie w tym kodzie dzieje się najważniejsza część. Bo dla mnie nie byłby to kontroler winksmiley.jpg A to jaki widok mi odpowiada do prezentacji danych modelu ustalam kontrolerem. Jak dla mnie to jest właśnie MVC: Model wybiera i obrabia dane, Widok je wyświetla, a Kontroler przekazuje dane Modelu do odpowiedniego Widoku. W Twoim przypadku jest tak: Kontroler pobiera dane z Modelu i dopiero w kontrolerze je obrabia i potem każe widokowi wyświetlić. Dla mnie to już pogwałcenie zasad MVC, ale wiem, że wielu programistów tak robi, zwłaszcza przy walidacji danych, bo likwiduje to kilka problemów, choćby z przepychaniem informacji o błędach i powtórnym wypełnieniu formularza tymi samymi danymi co przed wysłaniem. Rozumiem więc, że Twoje podejście jest wywołane doświadczeniami praktycznymi. Dlatego też nie uważam tego co napisałeś za błąd i nie zamierzam się kłócić w tak naprawdę nieistotnej sprawie. Po prostu zastosowałeś podejście praktyczne do pewnych problemów wynikające z doświadczenia programistycznego. Ja mam inne doświadczenia i stąd te różnice między nami.

Po prostu patrzymy na to samo z innych perspektyw. To widać już na poziomie podziału na klasy. Ja dla przykładu nie widzę sensu klasy dostawa, za to brakuje mi klasy produktu, bo z opisu sądząc można odnieść wrażenie, że dostawa istniejącego produktu do sklepu jest czymś nowym smile.gif A przecież to tylko zmiana pola dostępna_ilosc dla klasy produkt. Dostawa może być ewentualnie klasą widoczną dla admina z wyszczególnieniem, że tego dnia a tego do sklepu dotarło tyle jednostek produktu takiego i takiego lub informacje związane z obsługą dostawy do klienta jego zamówienia. Jak już podkreśliłem ja i wielu innych w tematach -> wykładni MVC jest tyle ile stosujących je osób. Dla mnie patrzysz na MVC z poziomu aplikacji jako całości strony, a ja od strony roli różnych klas w niej. Stąd co innego wkładamy do nazwanych tak samo klas. By można mówić o błędnym myśleniu któregokolwiek z nas, ale musielibyśmy mieć już z góry narzucony schemat podziału klas. Tego zaś nie mamy...

Ten post edytował thek 15.10.2009, 15:07:49


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
jmail
post
Post #10





Grupa: Zarejestrowani
Postów: 352
Pomógł: 53
Dołączył: 10.08.2009

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


nie no to są dwie zupełnie różne rzeczy.

Jeżeli klasy rozpatrujesz jako model MVC to oczywiście masz rację, ale przez to zaciemniasz cały obraz. Rozdrabniasz aplikację na setki mniejszych "aplikacji"

Poza tym

Model - baza danych i operacje się na niej dziejące
Kontroler - logika aplikacji (w tym również walidowanie danych tongue.gif)
Widok - wyświetlenie danych


Co do dostawy to wydzieliłem tą klasę z jednego prostego powodu. Dla mnie dostawa zawsze wiązała się z fakturą i całą księgowością, dlatego poleciała na osobną klasę. Co do produktu masz rację. Brakuje go jako klasy. Brakuje również klasy magazyn (skąd wiesz, że sklep ma jeden winksmiley.jpg ) i tak dalej. Wszystko zależy od perspektywy z jakiej patrzysz na sklep internetowy.

smile.gif

Ale to nie programista jest od tego, żeby to planować biggrin.gif dlatego właśnie analitycy projektowi koszą taką kapuchę za zamodelowanie rzeczywistości w aplikacji. Bo jak źle zamodelują to będzie kaszana z wydajnością.
Go to the top of the page
+Quote Post
dr4ko
post
Post #11





Grupa: Zarejestrowani
Postów: 49
Pomógł: 4
Dołączył: 16.07.2008
Skąd: Gdańsk

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


Cytat(jmail @ 15.10.2009, 12:53:12 ) *
Bo mnie zaraz coś trafi. Nie myl koledze.

Walidacja -> Model - bzdura - kontroler
Rejestracja -> Model - bzdura - kontroler
Logowanie -> Kontroler - no wreszcie coś rozsądnego
Wylogowanie -> Kontroler - i znowu coś rozsądnego
Nowe hasło -> Model - bzdura! - kontroler
Zmień hasło -> Model - bzdura! - kontroler
Zmień dane -> Model - bzdura! - kontroler
Pokaż rabat -> Widok - bzdura! - kontroler

Nie myl pojęć

Aplikacja ma być podzielona na warstwy a nie klasy. Poza tym są klasy do łączenia się z bazą danych i do wykonywania zapytań. Więc to one są Model'em. Widok to będzie mechanizm parsujący templatkę, a wszystko co się między nimi odbywa jest kontrolerem. Stworzenie zapytania (stringa) może być częścią kontrolera albo modelu - Twoja sprawa jak to zrobisz. Ale już walidacja w php (czy wszystkie dane zostały wpisane) jest czystym kontrolerem.


Pozwolę się nie zgodzić. MVC nie jest takie proste. Po pierwsze - model nie powinien bezpośrednio grzebać w bazie, od tego jest Data Access Layer. Co prawda DAL jest powiązany nierozłącznie z modelem ale samo połączenie z bazą i jego obsługa nie powinna się znajdować bezpośrednio w modelu. No ale nie o tym chciałem tu napisać.

Jak sama nazwa mówi, warstwa kontrolera służy do tego by kontrolować aplikację.Weźmy przykład zmiany hasła użytkownika:

View - wyświetla formularz zmiany hasła, użytkownik wpisuje hasło i klika button "zapisz". Informacja zostaje wysłana do controllera.
Controller - niech to będzie metoda changeUserPassword(). Powinna ona pobrać model aktualnie zalogowanego użytkownika, pobrać z posta nowe hasło, wykonać za pomocą helpera walidację hasła i wywołać na modelu użytkownika metodę changePassword(). W razie wystąpienia błędów powinna wyrzucić je do widoku.
Model - changePassword() wywołuje klasę DAL, ustawia za jej pomocą nowe hasło, zapisuje dane i wykonuje dodatkowe operacje typu ustawienia daty aktualizacji, czy wysłanie maila do użytkownika.

Controller jest warstwą przejściową, nie powinna ona być świadoma warstwy modelu. Ją interesują tylko dane wchodzące i wychodzące i czy są one prawidłowe, a nie co się z nimi dzieje. W skrócie - w controllerze nie przetwarzamy danych, co najwyżej je formatujemy i walidujemy.


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





Grupa: Zarejestrowani
Postów: 352
Pomógł: 53
Dołączył: 10.08.2009

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


dr4ko czekaj czekaj. czy to nie jest tak, że model to jest własnie baza danych? przecież DAL jest właśnie warstwą programowalną modelu. to do niej kontroler musi wysłać dane i powiedzieć co z nimi zrobić. Nie możesz mówić, że kontroler ma być nieświadomy modelu bo on musi model poprosić o konkretne dane, albo konkretne dane mu przekazać.

Z widokiem masz rację bezdyskusyjnie.

Cytat
Kontroler jest odpowiedzialny za odczyt danych z bazy danych (utworzenie modelu) i przekazanie ich do warstwy widoku (interfejsu użytkownika). Gdy użytkownik wybierze pokaż kolejne, wtedy odwołanie jest przekazywane do kontrolera, który ponownie pobiera dane i przekazuje do widoku tą samą drogą.


co z resztą jest zbieżne z tym czego mnie na uczelni uczono

Cytat
Praktycznie każda aplikacja WWW korzysta z baz danych - operacje na bazach stanowią modele danych. Szablony HTML odpowiedzialne za wygląd i wyświetlanie danych są częścią widoków (np. Smarty). Kod odpowiedzialny za wykonanie określonych operacji (spinający wszystko razem) tworzy sterowniki.


Poza tym jak to sobie wyobrażasz? Kontroler niświadomy modelu to co? Podaj mi jakiekolwiek dane a ja z nimi nie będę wiedział co zrobić? oO Przecież to się kupy logicznej nie trzyma oO
Go to the top of the page
+Quote Post
dr4ko
post
Post #13





Grupa: Zarejestrowani
Postów: 49
Pomógł: 4
Dołączył: 16.07.2008
Skąd: Gdańsk

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


Cytat(jmail @ 15.10.2009, 16:03:40 ) *
dr4ko czekaj czekaj. czy to nie jest tak, że model to jest własnie baza danych? przecież DAL jest właśnie warstwą programowalną modelu. to do niej kontroler musi wysłać dane i powiedzieć co z nimi zrobić. Nie możesz mówić, że kontroler ma być nieświadomy modelu bo on musi model poprosić o konkretne dane, albo konkretne dane mu przekazać.


Może źle się wyraziłem. Kontroler nie powinien być świadomy charakteru modelu. Co kontrolerowi do tego czy wysłać maila potwierdzającego czy nie? Albo co kontrolerowi do tego czy dane są pobierane z bazy czy z pliku xml? Kontroler reaguje na sygnał z UI, sprawdza jego poprawność i przekazuje dalej, nic poza tym. Po prostu cała logika biznesowa powinna być zawarta w modelu. Może bardziej obrazowy przykład:

Użytkownik za pomocą programu chce włączyć drukarkę. Klika przycisk. Informacja wędruje do kontrolera który sprawdza czy to na pewno dobry przycisk. Jeśli tak wywołuje komendę "włącz drukarkę" na modelu który w tym przykładzie jest fizyczną drukarką i oczekuje na informację zwrotną czy drukarka się włączyła czy nie. I nic poza tym, kontroler nie zajmuje się inicjalizacją wszystkich podzespołów i protokołów drukarki, drukarka robi to sama. Dzięki temu gdy kupimy nową drukarkę innej firmy nie musimy przepisywać całego kontrolera, tylko podpinamy ją pod już istniejący i będzie działała jak trzeba bo cała logika specyficzna dla danej drukarki jest zamknięta w samej drukarce, czyli naszym modelu.

Mam nadzieję że to co napisałem jest zrozumiałe smile.gif

Aha. Co do modelu będącego jednocześnie DAL czyli bazą danych. W prostych aplikacjach to może działać ale w dużych nie ma szans. Prosty przykład z systemu który rozwijamy w mojej firmie - mamy kilka rodzajów użytkowników, każdego opisuje około 5 tabel, z których tylko 3 są wspólne. Powiedz mi jak to obsłużyć korzystając tylko z DAL tongue.gif

Ten post edytował dr4ko 15.10.2009, 15:27:05


--------------------
devFactor
Go to the top of the page
+Quote Post
jmail
post
Post #14





Grupa: Zarejestrowani
Postów: 352
Pomógł: 53
Dołączył: 10.08.2009

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


no i właśnie o to chodzi. model jest tylko zbiorem danych. logika właśnie spoczywa na kontrolerze. obrazując podobnie do Twojego przykładu

mamy workflow z 20-oma krokami. user wykonał 11-ty krok. To kontroler decyduje o tym, żeby do modelu wysłać sygnał daj mi dane 12 kroku. oczywiście nie interesuje go co jest pod spodem czy xml czy cvs czy baza. on chce dostać dane. i teraz włąśnei DAL sprawdza co w konifugracji przechowuje dane i zwraca dane 12 kroku. Natomiast kontroler musi rozdzielić logikę biznesową, czy teraz maila wysłać czy może sms'a.

W założeniu które napisałeś wychodziłoby na to, ze kontroler powinien nazywać się walidator a nie sterownik czy kontroler
Go to the top of the page
+Quote Post
dr4ko
post
Post #15





Grupa: Zarejestrowani
Postów: 49
Pomógł: 4
Dołączył: 16.07.2008
Skąd: Gdańsk

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


Logika biznesowa powinna być zawarta w modelu, a kontroler służyć tylko do obsługi UI. Robiąc inaczej niszczy się cały zysk z MVC czyli wymienialność modelu bez ruszania całej reszty. Powiedzmy że wymieniłeś model na inny. Teraz przy dodaniu wpisu do bazy użytkownik nie ma dostać smsa tylko np informacja ma się pojawić na twitterze. Nie dosyć że musisz zaimplementować tą funkcjonalność w modelu, to jeszcze musisz usunąć wszystkie odwołania do sendSms() w kontrolerze i dodać wywołania addToTwitter(). Podwójna robota. Zrozum, że użytkownik nie prosił o wysłanie smsa czy maila, on prosił o dodanie wpisu i tylko tym się powinien zająć kontroler, a to że model biznesowy przewiduje notyfikację użytkownika o akcji jest już poza kręgiem zainteresowania kontrolera.


--------------------
devFactor
Go to the top of the page
+Quote Post
jmail
post
Post #16





Grupa: Zarejestrowani
Postów: 352
Pomógł: 53
Dołączył: 10.08.2009

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


to jest Twoja opinia. moja jest taka, że jeżeli wpis ma się pojawić na twitterze to trzeba tą funkcjonalność zaimplementować w kontrolerze a nie w modelu. Bo co? przebudujesz bazę danych żeby na twitterze się pojawiało? Model to baza danych i ewentualnie jej warstwa programowalna a nie funkcjonalności w php jakie sobie umyślisz
Go to the top of the page
+Quote Post
dr4ko
post
Post #17





Grupa: Zarejestrowani
Postów: 49
Pomógł: 4
Dołączył: 16.07.2008
Skąd: Gdańsk

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


Ok, ja się poddaję, nauczyciel ze mnie kiepski. Ale tu masz to wytłumaczone czarno na białym:
http://java.sun.com/blueprints/patterns/MVC-detailed.html

Może producent javy, dla której wymyślono MVC, będzie dla ciebie bardziej wiarygodnym źródłem wiedzy niż ja.


--------------------
devFactor
Go to the top of the page
+Quote Post
thek
post
Post #18





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Dr4co ma IHMO rację. Przyłącze się do przykładu z wysłaniem danych. To model ma wiedzieć gdzie są dane i w jakiej postaci. Rzucono przykład zmiany z sms na twittera. Myślę, że dobrze ilustrujący problem. Jak dodano, pociąga to za sobą zmiany zarówno w kontrolerze, jak i modelu w przypadku stosowania modelu aplikacji przedstawionego przez jmaila. Tymczasem jest to do wychwycenia już przez sam model, który może przechwycić tę informację z pliku konfiguracyjnego bez pośrednictwa kontrolera. Kontroler z kolei może mieć wpływ na konfigurację, ale przed lub po operacji. Nie w trakcie. Powiedz mi czy przesyłając formularzem fotografię decydujemy w kontrolerze czy wywołamy createimagefrompng, gif czy jpg? To analogia. Model ma wykryć z czym ma do czynienia i się dostosować. Można więc porownać to do obróbki w gd. Nieważne co wprowadzamy... Kontroler oczekuje zawsze obiektu gd, nie zaś pliku jpg, bo nie wie, czy to na pewno jpg będzie. A może ktoś przysłał plik png. Czy użycie imagecreatefromjpg na pliku png da prawidłowy rezultat? Nie. Każdy format jest przetwarzany do takiego obiektu, na którym operacje są już niezależne od źródła, natywnego dla narzędzia. Przykład z drukarką też jest dobry. Kontroler wywołuje jedynie funkcję print(). To model ma wiedzieć, która drukarka jest domyślna, czy drukować w skali szarości czy kolorze. A może do pliku? To wszystko jest zaszyte w konfiguracji i model ma do tego dostęp. W zależności od sytuacji sam zdecyduje jak się zachować. Model ma to w swoich atrybutach. Wcale nie przeszkadza to wymuszaniu przez kontroler na modelu konkretne zachowanie, niezależne od jego domyślnego. Wystarczy, że sam zainicjuje model o innych parametrach. A to kontroler może zrobić tyle, że model z kolei może mu na to nie pozwolić, twierdząc że drukowanie nie jest możliwe bo brak mu sterownika tej drukarki winksmiley.jpg


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
jmail
post
Post #19





Grupa: Zarejestrowani
Postów: 352
Pomógł: 53
Dołączył: 10.08.2009

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


ale chwilę. To co dałeś to jest modyfikacja pure MVC. W załozeniach MVC Model z Widokiem nie mają żadnego powiązania a w linku który dałeś jest. To jakby zbliżone już jest do modelu WPF a nie czystego MVC

LOL? z tym zdjeciem? To może zacznijmy zdjecia do blobów do bazy pchać..... wtedy to rzeczywiście model może to obsługiwać....

Ten post edytował jmail 15.10.2009, 16:31:37
Go to the top of the page
+Quote Post
dr4ko
post
Post #20





Grupa: Zarejestrowani
Postów: 49
Pomógł: 4
Dołączył: 16.07.2008
Skąd: Gdańsk

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


Bzdura. To co podałem to jest najczystsze MVC jakie może być bo ze źródła które je wymyśliło. W założeniu widok powinien otrzymać callback po operacji bezpośrednio z modelu lub za wykorzystaniem observera z pominięciem kontrolera. To dla php uproszczono sprawę i włączono do kontrolera funkcję obserwatora.
Co do dalszej części twojej wypowiedzi to zacytuję, bo chyba poza obejrzeniem obrazków nie czytałeś:
Cytat
Model - The model represents enterprise data and the business rules that govern access to and updates of this data. Often the model serves as a software approximation to a real-world process, so simple real-world modeling techniques apply when defining the model.


A co jeśli aplikacja nie ma bazy danych? Z twoim tokiem myślenia to architektura MVC nie mogłaby istnieć w takim przypadku co już u samo w sobie jest kompletnym absurdem.


--------------------
devFactor
Go to the top of the page
+Quote Post

2 Stron V   1 2 >
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: 21.08.2025 - 10:28