Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MVC] Czy dobrze interpretuję ?
Forum PHP.pl > Forum > PHP
matix
Witam,

Ciągle zastanawiam się, czy dobrze interpretuję zasadę MVC.

Chciałem napisać coś takiego:

KONTROLLER: Index.Controller.php:

Pobiera $_GET['view'] i zwraca $this -> setView():

  1. <?
  2. class aController 
  3. {
  4. private $sView;
  5.  
  6. function __construct() 
  7. {
  8. $this -> sView = $_GET['view'];
  9. self::setView();
  10. }
  11.  
  12.  
  13. function setView()
  14. {
  15. require_once('view/'.$sView);
  16. }
  17. }
  18. ?>


Następnie MODEL pobiera dane z mysql z danego projektu i zwraca:


  1. <?
  2. class db 
  3. {
  4. function __get() {
  5. while (...) 
  6. {
  7. $oArray[] = $db -> id;
  8. }
  9.  
  10. return $oArray;
  11. }
  12.  
  13. }
  14. ?>


W ostateczności Widok pobiera wszystko i generuje HTML:

  1. Klient o ID: <?=$db['id'];?><br/>
  2. Pobrał .... <?=$db['nazwa'];?>
  3.  
  4. To jest przykładowa tresc pliku widoku.



Męczy mnie także pytanie, jak to wszystko połączyć, zeby działało?
Chodzi o większą ilość widoków, lub modeli.

Proszę mnie nie odsyłać do artykułów, bo z nich nic się (niestety) nie można dowiedzieć.

Pozdrawiam, Matix: )
ActivePlayer
kontroler:
- sprawdza dane z geta, posta itd itd
- decyduje ktora akcje wykonac

model:
- pobiera//wstawia//edytuje dane w bazie
- obrabia dane, ogolnie operacje na informacjach

widok
- wyswietlanie

akcja
- uzywa modeli zeby cos wykonac

np akcja showNews uzywa modelu news (np $newsFinder->getNews($id)), i wywoluje odpowiedni widok a on wyswietla to co zostalo pobrane
Jabol
Widok wywołuje model aby pozyskać dane lub kontroler gdy wywołana zostanie akcja. Widok może też zostać zmieniony niezależnie od kontrolera ani modelu, np. przy zmianie kryteriów sortowania. Obsługuje "logikę wyświetlania".
Model zmienia widok, gdy sam zostanie zmieniony, nie wywołuje kontrolera. Przechowuje informacje. Obłsuguję "logikę danych".
Kontroler zmienia model oraz obsługuje akcje. Kontroler to logika aplikacji.

Akcja - to zapytanie do kontrolera, wywołanie kontrolera. Nie wydaje mi się też żeby kontroler decydował którą akcje wykonąć. To akcja decyduje który kontroler wywołać.

Co do przykładu powyżej. ShowNews to akcja, która wywołuje kontroler News. Kontroler ten nie modyfikuje modelu, wyświetla natomiast widok, który pobiera z modelu dane. Raczej tak rysowłabym te zależności. Dlatego przygotowywanie danych do wyświetlenia już na poziomie kontrolera to troszkę wg mnie za wcześnie. To powinien zrobić widok.

To taki prosty opis zależności. Widok może mieć odniesienia do akcji różnych kontrolerów. Tak samo kontroler po wywołani może zmienić widok - nie tylko zmienić aktualny widok, ale również zmienić samą instacje widoku.
Tak to łaczysz.

Pozdrawiam
jastu
Hm...ja korzystam z trochę innej interpretacji, możliwe że prostszej, może Ci się przyda ten opis ale uwag też chętnie posłucham.
Mam jeden plik index.php który jest jądrem (logiką) aplikacji, jeden plik Controller który filtruje dane z GET i POST po czym odpala odpowiednią akcję (której nazwa i paramerty są w URL). Akcja wykonkuje operację na modelu po czym ustala nazwę widoku. Całość pracy polega na dodaniu pliku akcji i szablonu widoku. Można przygotować odpowiednie wersje Controllera pod różne rodzaje URLi, a obecnie testuję różne szablony bo smarty wg xDebuga trochę mi zbyt wiele czasu wykonania skrytpu zabierają.

Rozumiem jak działają łańcuchy akcji ale nie potrafię ich zaimplementować, napisać (np. jak przechodzić z akcji do akcji i w jakiej postaci zwracane sa ewentualne wyniki (błędy) wykonanej akcji ?).
koodlaty
Cytat(matix @ 25.05.2007, 23:02:58 ) *
  1. <?
  2. class aController 
  3. {
  4. private $sView;
  5.  
  6. function __construct() 
  7. {
  8. $this -> sView = $_GET['view'];
  9. self::setView();
  10. }
  11. function setView()
  12. {
  13. require_once('view/'.$sView);
  14. }
  15. }
  16. ?>

Jeśli nie zamierzasz wywoływać metody statycznie, zamiast:
  1. <?php
  2. ...
  3. self::setView();
  4. ...
  5. ?>

bardziej po bożemu było by tak:
  1. <?php
  2. ...
  3. $this -> setView();
  4. ...
  5. ?>

Jeśli natomiast masz zamiar używać metody statycznie - konstrukcja winna wyglądać:
  1. <?php
  2. public static function nazwaMetody(){...self::mojePoleLubMetoda...}
  3. ?>


(To tak na marginesie jeśli mówimy o PHP5 smile.gif )
matix
Ok,
mniej więcej rozumiem i dziękuję za wszystkie przemyślenia na temat MVC.

Mam teraz pytanie, czy np:

Skrypt, który odbierze zmienną $_GET['type'] i wyświetli odpowiedni dla niego sposób widoku, będzie w kontrolerze ? Jeśli tak, to w jaki sposób powinien wyglądać ?
Może tak:

  1. <?
  2. class Controller 
  3. {
  4. private $_sType;
  5. private $_aType;
  6.  
  7. function __construct($sType) {
  8. $this -> _sType = $_GET['sType'];
  9. }
  10.  
  11. public static function _set() {
  12. switch($this -> _sType) {
  13. case 1: $this -> _aType = 'rss'; break;
  14. case 2: $this -> _aType = 'news'; break;
  15. }
  16.  
  17. return $this -> _aType;
  18. }
  19.  
  20. }
  21. ?>


Dałoby to radę?smile.gif

Pozdro biggrin.gif
koodlaty
Kod odbierajacy i filtrujacy dane z POST/GET (i wszelkie dane pochodzace od użytkownika) powinien znajdować się w metodach kontrolera, bardzo esencjonalnie zasady konstrukcji wzorca MVC podał ActivePlayer.
Polecam lekture dokumentacji Zend Framefork-a - kopalnia wiedzy o wzorcach i OOP.

Źle natomiast zrozumiałeś zastosowanie metod statycznych.
Nie ma powodu by Twoja metoda _set() była statyczna. Jej statyczne wykorzystanie i tak nie będzie mozliwe bo odnosi się do pól obiektu. Metody statyczne wywolywane są bez tworzenia obiektu, nie mogą więc odwolywać się do jego pól.

Opisując Ci sposób tworzenia metody statycznej chcialem powiedzieć że statyczne wywolanie self::setView(); było niepotrzebne i gdyby setView() odnosiło się do pól klasy jej działanie okazać by się moglo inne niż oczekiwane.

W tym konkretnym przypadku zamiast
  1. <?php
  2. self::setView();
  3. ?>
powinno być
  1. <?php
  2. $this -> setView();
  3. ?>
to wszystko.

Konstrukcja:
  1. <?php
  2. public static function _set() {
  3. switch($this -> _sType) {
  4. case 1: $this -> _aType = 'rss'; break;
  5. case 2: $this -> _aType = 'news'; break;
  6. }
  7.  
  8. return $this -> _aType;
  9. }
  10. ?>


Nie bedzie mogla być wywolywana statycznie, poza tym jest to bezzasadne.
sf
Proponowałbym wprowadzić dwie klasy - Request (przechowuje zmienne get / post ) i Response (odpowiedzialna za wyświetlanie). W mojavi3 bodajże tak jest winksmiley.jpg

U mnie kontroler jest jeden i to on uruchamia zależnie od $Response->action odpowiednią akcję winksmiley.jpg Jest także odpowiedzialny za obsługę łańcucha akcji oraz autoryzację (niektórzy ten element wyodrębniają z frameworka, ale wydaje mi się, że niepotrzebnie).
Cysiaczek
Cytat
Rozumiem jak działają łańcuchy akcji ale nie potrafię ich zaimplementować, napisać (np. jak przechodzić z akcji do akcji i w jakiej postaci zwracane sa ewentualne wyniki (błędy) wykonanej akcji ?).


@jastu Co do zwracania błędów, to można się długo spierać. Ja rozwiązałem to poprzez zgłoszenie stanu aplikacji, co podpatrzyłem w książce (ok, error, jakiTylkoSobieWymyslisz). Łańcuchy akcji z kolei mi sie udało zaimplementować. Zapraszam do obejrzenia małej demonstracji (sorry za kiepską jakość, ale komp strasznie zwalniał przy nagrywaniu : )

@sf - Widzę, że mamy podobnie : >

żądanie -> rozwiązanie żądania (tworzy początkowy łańcuch akcji) -> wykonanie żądania (wywoływanie w pętli akcji i ewentualna modyfikacja łańcucha akcji) -> zebranie danych do wyświetlenia -> Output (rózne np, XML, HTML)

i jeszcze filmik, który niektórzy już widzieli
Filmik prezentuje między innymi jeden ze sposobów obsługi braku parametru żądania (id) i dwie różne reakcje na ten błąd.
http://cysiak.freeweb7.com/kvktest3 (plik video w formacie Theora, 2.8 MB)

Pozdrawiam.
Ludvik
Cytat
Akcja wykonkuje operację na modelu po czym zwraca odpowiedni obiekt widoku.

Tak być nie powinno. Akcja nie ma prawa być powiązana w żaden sposób z obiektem widoku. MVC polega na oddzieleniu od siebie tych trzech warstw, więc wprowadzanie zależności pomiędzy modelem a widokiem łamie podstawowe zasady tego wzorca. Zmiana widoku spowoduje katastrofę w klasach akcji... Model powinien zwracać kontener z danymi, który następnie zostanie przekazany do widoku, tak aby nie były tworzone powiązania pomiędzy warstwami.

Sam pracuję w tej chwili nad implementacją MVC. Kontroler u mnie integruje całą aplikację, posiada wymienne Dispatchery, które tłumaczą żądanie HTTP na żądanie wykonania łańcucha akcji. Przed wykonaniem łańcucha, żądanie musi przejść przez filtry, w których np. można umieścić autentykację i autoryzację. Następnie kontroler iteruje przez kolekcję obiektów wywołujących akcje (czyli po prostu wykonuje kolejne akcje z łańcucha). W razie zmiany łańcucha, zostaje o tym poinformowany kontroler, który w razie czego wróci na jego początek. Kwestia implementacji obserwatora. Nad widokiem jeszcze myślę, gdzieś to upchnę po łańcuchu akcji... Dane są przesyłane w odpowiednich obiektach pomiędzy akcjami. W obiekcie kontekstu można zapisać informacje dotyczące całego żądania, czyli stan sesji itp...
jastu
Cytat
Zmiana widoku spowoduje katastrofę w klasach akcji...
Czy możesz dokładniej opisać ? Normalnie (chyba wg wzorca) to controller odpowiada za zarządzanie akcjami(łańcuchami) i w zależnosci od wyniku uruchamia widok ... u mnie jeden dla całej aplikacji controller(sprawdza ządanie) wywołuje jedną dla każdego żadania akcję i dopiero ona w zależności od wyniki operacji na modelu określa widok - ale widok uruchamia controller. W ten sposób tworzenia aplikacji ogranicza się do przygotowania szablonów widoku i pisania akcji.

Powyższy opis sprawdza się przy aplikacjach o małym zróżnicowaniu uprawnień. Obecnie korzystając z tego modelu budowy do modelu trzeba wysyłać uprawnienia bierzącego użytkownika ( angrysmiley.gif ). Przeczytałem kilka wątków o uprawnieniach użytkowników ale czytam chyba ze zbyt małym zrozumieniem - jak w MVC zarządzac uprawnieniami - musiałyby być przekazywane do Controllera ? do Widoku ? skąd ma obiekt widoku wiedzieć czy dany przycisk ma być wyświtelony czy nie ?
Cysiaczek
Obiekt widoku nie powinien nic wiedzieć o logice systemu. Jeśli chcesz wyświetlać coś, co jest zmienne, to możesz przesłać informacje z kontrolera do widoku w postaci jakiejś zmiennej i potem:
  1. <?php
  2. if ($costam){
  3. //wyswietl cos
  4. }
  5. else {
  6. //cos innego
  7. }
  8. ?>
jastu
Skoro widok ma nic nie wiedzieć o logice systemu a ma otrzymać tylko dane modelu to znaczy że uprawnienia muszą wędrować do akcji lub controllera (albo do obu)...bo rozumiem że model nie interesuje się uprawnieniami - jest to logiczne jeśli chodzi o operację na modelu i akcje ... W tej sytuacji skomplikowanie obsługi żadania z uwzględnieniem uprawnień jest wysokie i uzasadnia to tworzenie oddzielnego controllera dla kazdego wywołania strony...tylko gdzie podejmuje się decyzję o uprawnieniach użytkownika dla elementu strony www.
Próbujemy - jeśli ze strony www którą tworzymy da się wyodrębnić elementy które decydują o nawigacji (np.menu bądz jakiś panel przycisków) i stworzyć z nich obiekty należące do obiektu widoku oraz przekazać im informację o uprawnieniach to...?

Piszę o uprawnieniach bo męczy mnie pisanie oddzelnych panelów administracyjnych...przeglądam stronę i jest coś nie tak to klikam i poprawiam tongue.gif bez dodatkowego logowania i podobnych.
Pozdrawiam
Ludvik
Dobrym rozwiązaniem jest wzorzec View Helper.

Chodziło mi o to, że akcje mają operować na danych i co najwyżej je zwracać. Komunikacją pomiędzy widokiem a modelem ma się zająć kontroler. Tak czy inaczej model nie ma prawa nic wiedzieć o widoku, ma tylko zrobić to, o co go proszono (operacje na danych). Wybieraniem widoku powinien zajmować się kontroler...
Cysiaczek
Może ustalimy jakieś słownictwo? Każdy tu używa innych definicji i stąd większość problemów.
Implementacji MVC i innych wzorców jest wiele - wiele z nich również inaczej definiuje pojęcia.
Moja propozycja jest następująca:

Model (nie mylić z modelem dziedziny (domain model))
Pozyskiwanie danych z bazy danych lub innych źródeł - udostępnia zwarty interfejs dostępu do danych. Wykonuje wszystkie operacje za tzw. zamkniętymi drzwiami.

Controller
Z premedytacją nie definiuję tu Front Controllera i Application Controllera, bo ich implementacje najczęściej są łączone i z biegiem czasu wychodzą poza definicje tych wzorców.
Tu definicje będą dwie:
a ) Controller jako klasa zawierająca akcje
Najczęściej spotykana odmiana implementowana przez np, CakePHP. W jego ramach definiujemy metody naszej aplikacji. Jest on częścią logiki aplikacji

b ) Controller jako obiekt sterujący akcjami
Nie zawiera żadnych metod odpowiedzialnych za logikę aplikacji, a jedynie steruje obiektami (np. polecenia/akcji) i reaguje na wyniki ich działania.

Widok
Tu jest wiele niedomówień snitch.gif

a ) Widok jako obiekt systemu (Output)
Część systemu odpowiedzialna za renderowanie (tu strony www). Odwołuje się do danych (udostępnionych przez kontroler, bądź model, co zależy od implementacji).

b ) Widok jako szablon
W praktyce plik, który jest wypełniany danymi przez aplikację (php, smarty, opt, i inne)
Można podzielić na:
- pasywny - przyjmuje dane, ale nie odwołuje się do metod kontrolera, czy modelu, czy innych obiektów obecnych w systemie. Operuje tylko na danych, które otrzyma.
- aktywny - to samom co wyżej, ale może się odwołać do innych obiektów systemu

Akcja
Tu również definicje mogą być różne, choć wszystkie dotyczą logiki aplikacji

a ) Akcja rozumiana jako obiekt polecenia
Wykonuje działanie (np. modyfikuje pobrane z modelu dane) i jest w jakiś sposób sprzężona z kontrolerem

b ) Akcja rozumiana jako część kontrolera
Jest metodą w ramach klasy kontrolera

c ) Akcja rozumiana jako użytkownik kodu
Wykorzystuje zarówno kontroler, model jak i inne klasy/obiekty w systemie.


Sami widzicie, ile może być różnych znaczeń słowa kontroler. Większość z Nas używa różnych kombinacji, co prowadzi do nie zrozumienia. Jeśli ktoś widzi inne możliwe definicje, to niech się podzieli. Zapewne można jeszcze parę znaleźć - można by stworzyć osobny topik : )

Pozdrawiam.
Ludvik
Mi się wydaje, że MVC to nieco wyższy stopień abstrakcji niż klasy, obiekty itp... Dlatego nie powinniśmy rozmawiać o klasach, tylko o tym, czego te warstwy dotyczą.

Model, czyli warstwa biznesowa, to po prostu wszelkie operacje na danych. Widok, czyli warstwa prezentacji. Prościej mówiąc warstwa odpowiedzialna za interakcję użytkownika z aplikacją. Widok nie może być jednym obiektem, gdyż do widoku zaliczamy wszelkie żądania, odpowiedzi. Tego w jeden obiekt nie można zamknąć, głównie z powodu podstawowych zasad OOP. Kontroler, to warstwa, która pośredniczy pomiędzy dwiema poprzednimi. Odbiera żądania, rozdziela zadania, współuczestniczy przy transferze danych pomiędzy warstwami modelu i widoku. Nie ma tu znaczenia, czy rozmawiamy o Front Controllerze czy Application Controllerze.

Akcja to po prostu jakieś działanie na danych. Akcje oczywiście, można pozamykać w obiekty, ale tak czy inaczej akcja jest raczej ogólniejszym pojęciem.

Wzorce projektowe są narzędziem nie są związanym z warstwą implementacji. Dlatego np. programiści PHP korzystają z katalogu wzorców J2EE. Każdy implementuje wzorce na swój sposób. Inny nie znaczy zły... Natomiast w rozmowie o wzorcach, rozmawiamy o architekturze, a nie implementacji.
Cysiaczek
Cytat
Model, czyli warstwa biznesowa, to po prostu wszelkie operacje na danych

i za chwilę
Cytat
Akcja to po prostu jakieś działanie na danych. Akcje oczywiście, można pozamykać w obiekty, ale tak czy inaczej akcja jest raczej ogólniejszym pojęciem.


Mógłbyś to sprecyzować? Jakie działania wykonuje tu model? Model zawiera akcje, czy odwrotnie?

Zgadzam się, że MVC dotyczy warstw aplikacji, nie klas (nazwałem widok obiektem - powinienem warstwą). Wszystko rozbija sie jednak o implementację. Mówisz, że warstwa kontroli pośredniczy pomiędzy modelem, a widokiem. Mi się wydaje, że jej działanie może być nieco szersze. Może kontrolować sposób wyświetlania (np. może decydować o wyświetlaniu dokumentu w formie zwykłego XML, wysłać do przeglądarki stronę www, a nawet wysłać "goły" tekst - decyduje o tym żądanie, a nie model, czy widok).
Właśnie te różnice utrudniają komunikację, bo to, co dla Ciebie należy do warstwy modelu, u mnie robi akcja. To, co dla Ciebie już jest widokiem, dla mnie może jeszcze być logiką. Trudno więc rozmawiać o MVC bez podparcia się konkretną implementacją, bo jest to zbyt szerokie pojęcie.
Osobiście jako model mogę potraktować klasę:

  1. <?php
  2. class News{
  3.  
  4. function update() // zmiana właściwści obiektu
  5. function findById() // odnalezienie rekordu
  6. fucnction save() // zapis (przy użyciu jakiejś abstrakcji baz danych)
  7.  
  8. }
  9.  
  10. //uzytkować mogę tak:
  11.  
  12. class mojaAkcja extends Action(){
  13.  
  14. function Perform(){
  15.  
  16. $id=$params->get('id');
  17. $model=new News();
  18. $news=$model->findById($id);
  19. $news->setTitle('tytuł newsa');
  20. $model->update($news);
  21. $model->save();
  22. }
  23.  
  24. }
  25.  
  26. // żadanie przychodzi tak:
  27. // <a href="http://host.com/news/mojaAkcja/id_10" target="_blank">http://host.com/news/mojaAkcja/id_10</a>
  28. ?>


U Ciebie zapewne wygląda to inaczej i inne partie sytemu odpowiadaja za wykonanie tego żądania
url, który podałem jest rozpracowywany przez obiekty wchodzące w skład kontrolera, u Ciebie może to robić obiekt wogóle nie związany w kontrolerem.
Jednak jedno i drugie będzie dalej MVC snitch.gif

Pozdrawiam.
Ludvik
Tak jak pisałem, model to dane i operacje na nich. Skoro akcje zawierają operacje na danych, to zawierają się w modelu. Model jako obiekt nie powinien według mnie istnieć. Po prostu nie lubię pojęcia model, bo do niego zalicza się wszystko... Weźmy za przykład sklep internetowy.

Do modelu zaliczymy dane dotyczące produktów, działów, klienta oraz wszystkie operacje związane z nimi. Jeżeli klient kupuje książkę, to do modelu musimy wliczyć wszystkie operacje dotyczące produktu, zamówienia i użytkownika. Akcje odpowiadałyby za kolejne zadania: utworzenie zamówienia, związania zamówienia z użytkownikiem, dopisania produktu do list itd...

Cytat
Może kontrolować sposób wyświetlania (np. może decydować o wyświetlaniu dokumentu w formie zwykłego XML, wysłać do przeglądarki stronę www, a nawet wysłać "goły" tekst - decyduje o tym żądanie, a nie model, czy widok).

Żądanie jest elementem widoku, bo widok jest warstwą prezentacji. Z kolei warstwa prezentacji odpowiada za interakcję z użytkownikiem, a jest nią bez wątpienia wysłanie żądania w dowolnej formie. W aplikacjach okienkowych żądaniem jest np. naciśnięcie przycisku. W aplikacjach sieciowych tę rolę pełnią żądania, w szczególności HTTP. Racja leży po środku, bo obie warstwy są w to zaangażowane. Tak czy inaczej, wszystkie te działania prowadzą do ustanowienia komunikacji pomiędzy modelem a widokiem. Wszystko w końcu musi się trzymać kupy...

Na schemacie widać to doskonale:
http://java.sun.com/blueprints/patterns/im...ure-generic.gif
matix
Wybaczcie, ale z tego co widzę to MVC to jedno wielkie nieporozumienie, każdy go pisze inaczej i według innego jest to źle smile.gif No sory, ale poczytajcie se wszystkie posty;D

Mógłby w takim razie ktoś napisać jakiś prosty przykład z wykorzystaniem Controllera, Modelu i Widoku wraz z połaczeniem tego? Bo ja już teraz nic z tego nie wiem, jedyne co wiem to do czego to wszystko służy, lecz niestety każdy mówi, że w "tym czymś" ma być coś innego winksmiley.jpg
W takim razie proszę o przedstawienie waszych praktycznych przykładów z życia programisty korzystającego z MVC smile.gif

Pozdro biggrin.gif


-edit-

Btw. Który z tych dwóch: Controller czy Model powinien łączyć się do mysql. Chodzi o mysql_connect / mysql_close(nie mówię o mysql_query, itp) ?smile.gif
Cysiaczek
Przykład dotyczy wyświetlenia wartości wpisanej w pole formularza.
jest on bardzo prosty, a mój framework wymaga nieco nakładów pracy przy tworzeniu aplikacji, więc proste przykłady wyglądają dziwacznie.

plik index.php, czyli akcja index
unit oznacza nazwę modułu (mam tak, bo nie ma namespaces w php - jak będzie php6, to zmienie)
  1. <?php
  2. class unit_index extends Action{
  3.  
  4. function Perform(){
  5. $req=$this->AHelper->getReqRegistry(); //elementy żądania m.in dane przesłane URL i POST
  6.  
  7. if(!$req->has("tekst", "post")){ //jesli brak zmiennej tekst przesłanej przez post
  8. $this->setStatus("ERROR"); // zakomunikuj błąd kontrolerowi - wyświetli formularz
  9. return; //koniec
  10. }
  11. $this->data->tekst=$req->get("tekst", "post"); //Dodajemy $tekst do danych przekazywanych potem do widoku
  12. }
  13. }
  14. ?>


plik actions.xml zawierający informacje dla kontrolera dotyczące akcji i tego, jak ma reagować na różne zgłoszone przez nią stany

  1. <?xml version='1.0' standalone='yes'?>
  2. <actions>
  3.      <index>
  4.            <slot>index</slot>
  5.            <status>
  6.                  <ok>
  7.                        <view>pokaz</view>
  8.                  </ok>
  9.                  <error>
  10.                        <view>error</view>
  11.                  </error>
  12.            </status>
  13.      </index>
  14. </actions>


Teraz warstwa prezentacji

plik index.slot.php - sloty to miejsca, przez które pliki szablonów są wstawiane na stronę www
  1. <h1><?php $VHelper->get('index', 'unit'); //pobiera szablon wygenerowany przez akcję index z modułu unit ?></h1>


plik pokaz.tpl

  1. <?php print $tekst; //wyświetlamy naszą zmienną zadeklarowaną w akcji ?>


plik error.tpl - zostanie wyświetlony, gdy nie przesłano danych

  1. <form method="post" action="<?php print url(array("unit", "index"), '', true); ?>" />
  2. <input type="text" name="tekst" />
  3. <input type="submit" value="send" />
  4. </form>


---edit
Zobacz, że klasa akcji jest maksymalnie izolowana od warstwy prezentacji - nie wybiera sama pliku, który ma zostać wyświetlony - zgłasza tylko stan, a resztą zajmuje się jądro systemu. Podobnie działają przekierowania. Ba! można w ten sposób nawet wyrzucić wyjątek. Ten przykład nie zawiera manipulacji danymi, ale jeśli takie są konieczne, to robi się to właśnie w ciele akcji lub wydziela się następną akcję, która to robi (to już bardziej zaawansowana zabawa)
matix
@up: jesteś kolejną osoba, która myśli inaczej niz wszyscy. Co z tego wynika?
- to, że MVC polega tylko na tym, że te 3 rzeczy mają się ze sobą łączyć, w modelu mają być dane, w kontrolleru - 'mechanizmy' zarządzania a w widoku - prezentacja (np. szablony);
reszta, kto, jak wykona- jego inwencja i nie zmienia to faktu, że dalej trzymie się zasady MVC.

Czy nie mam racjii ?smile.gif
Cysiaczek
Tak. Masz rację. Ja też to zauważyłem, dlatego postanowiłem parę postów wcześniej pokazać, że sama debata na temat MVC jest dziwną debatą, bo to tak jakbyśmy debatowali nad rolą władz; ustawodawczej, wykonawczej i sądowniczej. Tu role są jasne, a różnią się jedynie implementacjami: mamy dwu izbowy parlament, radę ministrów i sądy. W USA z kolei nie ma premiera itd. itp.

Pozdrawiam.
menic
Tyle ile programistow tyle opini nt MVC snitch.gif
MVC jest to tylko ogolna idea. Jak to zaimplementujesz to juz zalezy tylko od twojej inwencji smile.gif

Tak w ogole to przydaloby sie jakis taki osobny temat wydzielic na to albo nawet i forum biggrin.gif
matix
Całe forum nie, ale może przynajmniej przykleić ten temat, bo wielu "młodych" webmasterów (w tym: ja) boryka się z tym właśnie problemem.

Pozdro biggrin.gif
sf
Cysiaczek ładnie to rozpisał jakie są podejścia do MVC i wydaje mi się, że byłby to dobry materiał na artykuł.
menic
@Cysiaczek: Wlascicie to czemu bloga nie prowadzisz snitch.gif ?
Cysiaczek
Może nawet zacznę, ale dopiero jak się uporam z frameworkiem i napiszę w nim silnik snitch.gif
menic
niedoczekanie snitch.gif tongue.gif
sf
właśnie... winksmiley.jpg mój się budował 2 lata, niby jest, ale ciągle jakieś poprawki tongue.gif
href
Przepraszam ze tak sie wcinam w inny temat, ale nie chcialem zakladac kolejnego tematu nt. mvc. Zdaje sobie sprawe ze mvc jest raczej 'poradą' w jaki sposob pisac aplikacje a juz od programisty zalezy w jaki sposob to sobie zaimpementuje, ale czy ponizszy kod mozna uznac za uproszczoną implementacje mvc? czy jesli powiem 'komuś' ze taka aplikacja jest napisana z wykorzystaniem wzorca mvc to nie wyglupie sie zbytnio? snitch.gif

model:
  1. <?php
  2. class news
  3. {
  4. public function add()
  5. {
  6. // dodawanie newsow
  7. }
  8. public function show()
  9. {
  10. // wyswietlanie newsow
  11. }
  12. public function delete()
  13. {
  14. // usuwanie newsow..
  15. }
  16. // etc.
  17. }
  18. ?>


kontroler
  1. <?php
  2. function __autoload($file)
  3. {
  4. include_once($file.'.php');
  5. }
  6. $news = new news;
  7. switch($_GET['mode'])
  8. {
  9. case 'add':
  10. $news -> add();
  11. break;
  12. case 'show':
  13. $result = $news -> show();
  14. foreach($result as $value)
  15. {
  16. $template->assign_block_vars('news',array( // przekazanie wartosci zmiennych do widoku
  17. 'title' => $result['title'],
  18. 'message' => $result['message']
  19. //etc.
  20. )
  21. );
  22. }
  23. break;
  24. case 'delete':
  25. $news -> delete();
  26. break;
  27. }
  28. ?>


widok:
  1. <!-- BEGIN news -->
  2. <dl>
  3. <dt>{news.title}</dt>
  4. <dd>{news.message}</dd>
  5. </dl>
  6. <!-- END news -->
kwiateusz
tak takie coś można nazwać mvc wszystkie warstwy są od siebie oddzielone i nie mieszają się ze soba smile.gif a podmiana któejś nie spowoduje zmian w innych warstwach.
miedzna
Model.php

  1. <?php
  2. class Model {
  3.  
  4. private $data;
  5.  
  6. function __construct() {
  7.  
  8. $this->data = false;
  9.  
  10. }
  11.  
  12. function calculate($name) {
  13.  
  14. $this->data[] = $name;
  15.  
  16. $len = strlen($name);
  17.  
  18. if ($len == 3) 
  19. $this->data[] = 'krótkie fajne imię';
  20. else
  21. if (($len > 3) && ($len < 6))
  22. $this->data[] = '... bez znaczenia';
  23. else
  24. $this->data[] = 'fantazja rodziców';
  25. }
  26.  
  27. function getData() {
  28.  
  29. if ($this->data) 
  30. return $this->data;
  31. else
  32. return 'Coś jest nie tak!';
  33.  
  34. }
  35.  
  36. } // class Model
  37. ?>




View.php

  1. <?php
  2. class View {
  3.  
  4. static function displayDefault() {
  5.  
  6. echo "<form method='POST' action=''>";
  7. echo "<p>Wprowadź imię: ";
  8. echo "<input type='text' name='name' value=''> ";
  9. echo "<input type='submit' name='send' value='Wyślij'>";
  10. echo "</form>";
  11.  
  12. }
  13.  
  14. static function displayError($error) {
  15.  
  16. echo "<p><b>Błąd:</b> {$error}";
  17. View::displayDefault();
  18. }
  19.  
  20. static function displayResults($results) {
  21.  
  22. echo "<p><b>Wyniki:</b>";
  23. echo "<p>Imię <b>".$results[0].
  24. "</b> oznacza <i>".$results[1]."</i>";
  25. echo "<p><a href='".$_SERVER['REQUEST_URI'].
  26. "'>dowiedz się więcej na temat swojego imienia</a>";
  27. }
  28.  
  29. } // class View
  30. ?>



Controller.php

  1. <?php
  2. class Controller {
  3.  
  4. private $error;
  5. private $result;
  6.  
  7. function __construct() {
  8.  
  9. $this->error = false;
  10. $this->result = false;
  11.  
  12. }
  13.  
  14. function processData() {
  15.  
  16. $this->userRequest();
  17.  
  18. if ($this->error)
  19. View::displayError($this->error);
  20. else
  21. if ($this->result)
  22. View::displayResults($this->result);
  23. else
  24. View::displayDefault();
  25. }
  26.  
  27. function userRequest() {
  28.  
  29. // DANE ZOSTAŁY WYSŁANE
  30. if (isset($_POST['send'])) {
  31.  
  32. $this->validate();
  33.  
  34. if (!$this->error) {
  35.  
  36. // PODSTAWOWE OBLICZENIA
  37. $model = new Model();
  38. $model->calculate($_POST['name']);
  39. $result = $model->getData();
  40.  
  41. // SPRAWDZANIE BŁĘDÓW W SAMYM MODELU
  42. if (!is_array($result))
  43. $this->error = $result;
  44.  
  45. else
  46. $this->result = $result;
  47.  
  48. }
  49. }
  50. }
  51.  
  52. function validate() {
  53.  
  54. if (empty($_POST['name']))
  55. $this->error = 'Wprowadź imię!';
  56. else
  57. if (strlen(strval($_POST['name'])) < 3)
  58. $this->error = 'Imię jest za krótkie!';
  59.  
  60. }
  61.  
  62. } // class Controller
  63. ?>




wykorzystanie, czyli jakiś tam index.php:

  1. <?php
  2. include("Controller.php");
  3. include("Model.php");
  4. include("View.php");
  5.  
  6. $controller = new Controller();
  7.  
  8. $controller->processData();
  9. ?>
sanchoo
mam pytanie o moja interpretacje... tzn o krytyke smile.gif bo pisze chyba juz 10 raz.. i zmieniam zmieniam i zmineiam.. a czasu nie mam za duzo:)
u mnie to dziala tak:
najogolniej mam ?dzial=1
Pobieram z bazy nazwe takiego dzialu i odpalam taki contlroler (jest dziedziczony z glonwego).
Przyklad spr. czy zalogowany admin/user.
Logowanie odbywa sie u mnie tak:
Contlorer sprawdza czy podalem dobry login i haslo oraz jakie mam prawa user/admin. i odpala mi taki podcontroler class admin (np.) .. ktory aktualizuje w bazie ("ostatnio zalogowany" itp..) jesli zalogowalem sie jako admin odpalam clase admin_view np:) ktora pobiera sobie info z modelu..co ma wyswielic po czym odpala assign i laduje do smartow..wyswietla:)


Mam pytania:
Potrzebuje dane z modelu jakos obrobic... posprawdzac itp... mam to zrobic na poziomie contlorera i wyslac do widoku?? czy tym sie ma zajac widok ..i ewentualnie skorzystac z funkcji kontolrera? np usuwanie posta z info czy "post zostal usuniety poprawnie" (taki przyklad) wybieram usun.. klikam ok strona sie przladowuje odpalany jest kontlorer ze sprecyzowna akcja ... ktora odwoluje sie do modelu i usuwa, jesli usunie zwraca true i teraz mam zrobic cos takiego np $usunieto=true (jesli usuneolo poprawnie winksmiley.jpg) new admin_view($usunieto);
WebCM
Ostatnio zaglądnąłem do części kodu PhpBB 3. Nasuwa mi się trochę inne rozwiązanie smile.gif Kontroler dołącza klasę modelu i tworzy obiekt. Stąd też pobiera tytuł strony i inne dane, a także pliku widoku (szablon?). Jest jednak kilka kwestii:
- do wyświetlenia błędu lub informacji też dołączamy widok (np. gdy mamy zdefiniowaną funkcję Info)?
- co wtedy, gdy korzystamy z 2 modelów (np. news, komentarze)?

Aktualnie mam kilka kontrolerów (admin, index, głosowanie, pobierz plik, wyświetl link, generuj kod z obrazka, AJAX), a modele dołączają się już w <body> (warstwy nie są obiektami, ale to nie ma znaczenia). biggrin.gif
macbirdie
Skoro wszyscy przedstawiają swoje interpretacje, i ja dołączę, bo mam pewne wątpliwości.
Zend Framework 1.0.1.
Jest sobie np. stronka główna.
Jak wiadomo stronka główna zawierać może kilka dynamicznie generowanych elementów, jak lista ostatnich newsów, wpisów na forum, liczniczki, inne.
Są też inne strony, które mogą zawierać różne zestawy innych elementów strony, w różny sposób wyświetlanych i mogą różnić się diametralnie od strony głównej.

Jest więc kontroler strony głównej i innych.
Myślałem długo, jak do tego podejść, ponieważ niby kontroler ma przypisany jeden widok, a jeden widok ma mieć przypisany jeden kontroler. Tylko jak tu ładnie i wygodnie tworzyć kolejne składające się z różnych dynamicznych elementów stronki, by nie dotykać za bardzo kodu?
Wymyśliłem zatem tak, że do każdego kontrolera jest przypisany pliczek konfiguracyjny. Ten zawiera informacje na temat elementów, jakie mają się w danej akcji pojawić, jakie dostają parametry i jakie szablony mają używać, by się wyświetlić.
Np. kontroler index ma akcję index, więc jest views/controllers/index/index.xml
Tam jest np.
nagłówek, szablon naglowek_normalny.phtml, tytuł: tytuł sajtu + tytuł aktualnej strony, aktualna data i parę innych pierdółek.
lista newsów, szablon newsy_główna.phtml, ile newsów: 10, kategoria: główna
lista postów forum, szablon: posty_forum_główna.phtml, ile postów: 15
itd.

Do każdego takiego elementu dynamicznego przypisana jest klasa, która zajmuje się pożywieniem elementu danymi z modelu/modeli, zatem można powiedzieć że to taki mały kontroler.

Moja klasa rozszerzająca Zend_Controller_Action (MacBirdie_Controller_PresentationAction, a co aaevil.gif ) działa tak że w init pobiera konfigurację dla kontroler/akcja, akcja kontrolera domyślnie nic nie robi, dopiero w post-dispatch pobierana jest informacja na temat elementów i zostają kolejno odpalane klasy tych elementów, te każdemu szablonowi Zend_View (na razie spróbuję standardowe phtml) wrzucają potrzebne dane, następnie widoczki są renderowane i dopisywane do response.

Czy to jest czy nie jest herezja MVCowa? winksmiley.jpg

Na takiej zasadzie od dawien dawna działa sajt stworzony przeze mnie daaawno temu, PDAclub.pl i jest to metoda bardzo wygodna, jednakże tam MVC nie stosowałem, więc nie wiem czy jakichś zasad nie naruszam.
Jeśli tak, jakie są inne podejścia do tego problemu?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2024 Invision Power Services, Inc.