Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MVC] Moj poczatek / implementacja
Forum PHP.pl > Forum > PHP > Pro > Archiwum Pro
Helios
Witam
Od niedawna zaczalem interesowac sie MVC. Ale w dalszym ciagu nie wiem czy dobrze rozumuje istote MVC. Dlatego postanowilem napisac prosty (powtarzam, prosty, system) zeby sprawdzic czy ide w dobrym kierunku. Prosze o komentarze, jesli chodzi o sam schemat i istote wzorca MVC.

Na poczatek przedstawie strukture katalogow:

./ - katalog glowny
actions/ - katalog przechowujacy pliki .ini do wybranej akcji mozemy podac co ma zostac wykonane nastepnie
configs/ - katalog z plikami konfiguracyjnymi - narazie nie uzyty
controllers/ - katalog z kontrolerami - narazie tylko kontroler glowny
models/ - katalog z plikami modeli
views/ - katalog z plikami widokow
index.php - plik glowny ktory uruchamia kontroler

Zaczynamy od poczatku - kod kontrolera:
  1. <?php
  2.  
  3. class Ctrl{
  4.  
  5. private $Request=false; // obiekt
  6. private $action; // nazwa akcji - nieobowiazkowa
  7. private $view; // nazwa widoku
  8. protected $model; // nazwa modelu - nieobowiazkowa
  9.  
  10. protected $objView; // obiekt widoku
  11. protected $objModel; // obiekt modelu
  12.  
  13. // konstruktor
  14. public function __construct($request){ 
  15.  
  16. // ustawianie pol klasy
  17. $this->view=$request->getParam('view');
  18. $this->view=($this->view) ? $this->view : 'main'; // ustawianie standardowego widoku
  19. // jesli zostal podany model ustawia jesli nie jest taki sam jak nazwa widoku
  20. $this->model=($request->getParam('model')) ? $request->getParam('model') : $this->view;
  21. // model z sufixem Mod
  22. $this->model.='Mod';
  23. // pobiera parametr akcji o ile zostal podany
  24. $this->action=$request->getParam('action');
  25.  
  26. // jesli zostala podana akcja laduje model i wykonuje odpowiednia czynnosc
  27. if($this->action){
  28. require_once('./models/'.$this->model.'.model.php');
  29. $this->objModel=new $this->model($request);
  30. $action=$this->action;
  31. $this->objModel->$action();
  32. do{
  33. // sprawdza czy plik konfiguracyjny akcji uwzglednia wykonanie kolejnej akcji
  34. $tmpCfg=parse_ini_file('./actions/'.$this->action.'.ini');
  35. $action=$tmpCfg['next'];
  36. // jesli tak to ja wykonuje itd.
  37. $this->objModel->$action();
  38. }while(!$tmpCfg['next']);
  39. }
  40. // laduje obiekt widoku
  41. $this->execute();
  42. }
  43.  
  44. public function execute($view=false){
  45. // sprawdza czy obiekt modelu juz istnieje czyli czy podana byla akcja
  46. if(!is_object($this->objModel)){
  47. require_once('./models/'.$this->model.'.model.php');
  48. $this->objModel=new $this->model($request);
  49. }
  50. // laduje obiekt widoku
  51. require_once('./views/'.$this->view.'.view.php');
  52. $this->objView=new $this->view($this->objModel);
  53. }
  54.  
  55. }
  56.  
  57. ?>

Zakladamy, ze uzytkownik wpisal: index.php?view=Users&action=addUser&userName=root
kontroler laduje wiec model UsersMod:
  1. <?php
  2.  
  3. class UsersMod {
  4.  
  5. public $addedUser;
  6. public $request;
  7. public $count;
  8.  
  9. function __construct($request){
  10. $this->request=$request;
  11. }
  12.  
  13. function addUser(){
  14. $this->addedUser=$this->request->getParam('userName');
  15. return true;
  16. }
  17.  
  18. function countUsers(){
  19. return $this->count++;
  20. }
  21.  
  22. function getAddedUser(){
  23. return $this->addedUser;
  24. }
  25.  
  26. function getUsersNum(){
  27. return $this->count;
  28. }
  29.  
  30. }
  31.  
  32. ?>

i wykonuje w nim akcje zmianu danych, a poniewaz akcja addUser() posiada plik konfiguracjny z wywolaniem jako kolejnej akcji countUsers wywoluje kolejna akcje. No i pozostaje wyswietlenie widoku Users:
  1. <?php
  2.  
  3. class Users {
  4.  
  5. function __construct($objModel){
  6. print 'Dodalem uzytkownika: '.$objModel->getAddedUser().' i teraz mam zarejestrowanych uzytkownikow: '.$objModel->getUsersNum();
  7. }
  8.  
  9. }
  10.  
  11. ?>


Co sadzicie o tym? Czy dobrze rozumuje istote MVC? Zapraszam do dyskusji...
hwao
Jeżeli to działą, to jest dobre... Nie ma "szablonowej" implementacji tego wzorca w zadnym z jezyków, dla tego trzeba tylko znac załozenia i tworzyc własne.

Tutaj masz opis wzorca, nie implementacji:
http://hwao.be/blog/2006/04/14/model-view-controller/

Raczej jak sa katalogi, to najmniej wazne poniewaz powinny byc ustawione przez stale (przynajmniej ja tak robie).

Troche wydaje mi sie dziwny ten kontroler, poniewaz jest jakis taki "malo" elastyczny. Napisz pare aplikacji na tym to Ci zaraz przyjdzie do glowy jakies lepsze rozwiazanie.

Umnie widok robi troche inna rzeczy, a to co jest u Ciebie, u mnie robi to system szablonów.
Cysiaczek
Cóż. To zależy, czy widok ma wyciągac dane, czy aplikacja te dane wstawiać smile.gif Niby różnica niewielka w praktyce, ale w podejściu do problemu ogromna :|
ActivePlayer
@hwao co widok robi u CIebie ?
hwao
Cytat(Cysiaczek @ 8.07.2006, 22:58 ) *
Cóż. To zależy, czy widok ma wyciągac dane, czy aplikacja te dane wstawiać smile.gif Niby różnica niewielka w praktyce, ale w podejściu do problemu ogromna :|

Widok, wyciagac dane?! Widok ma inne zadania! To model jest warstwa ktora powinna pozyskiwac dane, z różnych źródeł! Podsumowujac, widok otrzymuje gotowe dane z modelu i zajmuje sie obrobka ich (prezentacja uzytkonikowi), model zajmuje sie wyciaganiem danych.
Cytat(ActivePlayer @ 8.07.2006, 23:34 ) *
@hwao co widok robi u CIebie ?

Umnie głównym zadaniem widoku jest pozyskanie danych przez(od) modelu i poprzez system szablonów przedstawienie ich użytkownikowi.
ActivePlayer
u mnie element widok to 'class view extends smarty'...
w akcji pobieram poprzez model dane, assign do widoku, i display.
Cysiaczek
Cytat(hwao @ 8.07.2006, 21:49 ) *
Umnie głównym zadaniem widoku jest pozyskanie danych przez(od) modelu i poprzez system szablonów przedstawienie ich użytkownikowi.


O to mi chodziło - o pozyskanie danych. Inaczej - czy widok jest pasywny, czy aktywny. Nie chodziło o pozyskanie danych z bazy.

Ewentualne problemy z komunikacją wynikają z tego, że ja używam pojęcia <widok> na określenie szablonu/template'a/jakzwałtakzwał
Ociu
Jak na pierwsze starcie nie jest najgorzej.
Jak pisał hwao, niezbyt elastyczne to jest.

Ja podzieliłem kontrolę na: Controller, webController -> FrontController, BlockController; ConsoleController.
Prph
Witam,

Ostatnio napisalem (mam nadzieje) framework i z przyjemnoscia podziele sie moimi uwagami.

1. NAJWAZNIEJSZA ZASADA
Jezeli piszesz framework dla siebie - pisz go tak, aby byl wygodny dla Ciebie.

2. MVC
MVC mowi, ze masz miec model, widok i kontroler. Model nie wyswietla daych, widok nie grzebie w bazie. Kontroler umozliwia im jakas tam wspolprace.


Nie podoba mi sie struktura katalogow. Tzn ja zmianilbym ja na nastepujaca:

actions/ - kontrolery akcji
models/ - modele
views/ - widoki
configurations/ - konfiguracje wszystkiego co zbudujesz na owym frameworku (np. akcji lub bibliotek, ktore bys mogl pozniej dodac.)

konfiguracje mozesz zapisywac w plikach o przykladowych nazwach: DodajUzytkownikaAction.ini, UsunNewsaAction.ini, MojaBibliotekaJPEGLibrary.ini.

Teraz nieco do kontrolera. Ktos powiedzial, ze jest malo elastyny. No w sumie trudno go zrobic innego, jak kolega dopiero zaczyna.
Ja przyczepie sie do fragmentu nastepujacego:

  1. <?php
  2. if($this->action){
  3. require_once('./models/'.$this->model.'.model.php');
  4. $this->objModel=new $this->model($request);
  5. $action=$this->action;
  6. $this->objModel->$action();
  7. do{
  8. // sprawdza czy plik konfiguracyjny akcji uwzglednia wykonanie kolejnej akcji
  9. $tmpCfg=parse_ini_file('./actions/'.$this->action.'.ini');
  10. $action=$tmpCfg['next'];
  11. // jesli tak to ja wykonuje itd.
  12. $this->objModel->$action();
  13. }while(!$tmpCfg['next']);
  14. }
  15. // laduje obiekt widoku
  16. $this->execute();
  17. ?>


Dlaczego ladujesz model? To nie nalezy do kontrolera. Ja wiem, ze moze byc tak wygodnie. Ale sa akcje w ktorych z niego nie skorzystasz. Przyklad?

Akcja ktora wyswietla kominikat, jezeli nie znaleziono strony. Np masz akcje PokazZdjecia. Ktos wpisze adres:
jakasStrona.pl/akcja=PokazFotografie.

Jezeli kontroler nie znajdzie PokazFotografie to milo jest, jak odpalisz akcje np. NieZnaleziono. Ona wyswietli jedynie komunikat, zwroci Error 404 lub cos innego. Model nie jest tu najczesciej potrzebny.

Zrob tak:

1. Sprawdz o jaka akcje uzytkownik prosi. np: strona.pl/akcja=PokazZdjecie.
2. Jezeli jest pusta (np. podano strona.pl/), to ustaw domyslna (np. StronaGlowna).
3. Jezeli nie jest pusta, pobiez ja i sprawdz czy istnieje.
4. Jezeli nie, przypisz akcji akcje NieZnaleziono. Sprawdz czy istnieje (tak dla spokoju) i jak nie ma akcji (usunales ja, albu dysk padl winksmiley.jpg), to zglos jakis blad.

5. Jezeli akcja istanieje - uruchom ja.

Teraz akcja jezeli chce, prosi po model, ustawia sobie widok. Pobiera dane z modelu, przekazuje je widokowi. Widok moze wyswietlic, albo zwrocic kontrolerowi (w kontrolerze piszesz $oWidok = $oAkcja->uruchom()winksmiley.jpg. Wtedy kontroler ja wyswietla albo robi co mu sie podoba winksmiley.jpg

Zeby nie bylo malo, zalaczam fragmenty mojego kodu:
  1. <?php
  2. class Error403Action extends Action
  3. {
  4.  
  5. public function execute()
  6. {
  7. return Controller::getInstance()->getView('Error403'); // kontroleg glowny tworzy mi obiekt widoku o tej nazwie.
  8. }
  9. }
  10. ?>


  1. <?php
  2.  
  3. class Error403View extends ExtendedHtmlView
  4. {
  5. public function __construct()
  6. {
  7. parent::__construct(); // wywoluje konstruktor klasy bazowej. Raczej jest mi to potrzebne.
  8.  
  9. $this->setTemplate('Error403'); // ustawiam sobie szablon. Uzywam zwyklych szablonow php.
  10. }
  11. }
  12.  
  13. ?>


Dam jeszcze przyklad jak to jest z modelem:

  1. <?php
  2. class ShowPageAction extends Action
  3. {
  4. public function execute()
  5. {
  6. $oController = Controller::getInstance();
  7.  
  8. $sPageName = $oController->getContext()->getRequest()->getParameter('page', HttpRequest::GET);
  9.  
  10. if(is_null($sPageName))
  11. $sPageName = 'Index';
  12.  
  13. $oPageModel = $oController->getModel('Page');
  14.  
  15. if(!($aPage = $oPageModel->getPageByName($sPageName)))
  16. {
  17. $oController->forward(_ACTION_ERROR_404);
  18. return null;
  19. }
  20.  
  21. $oView = $oController->getView('ShowPage');
  22.  
  23. if(!empty($aPage['title']))
  24. $oView->setAttribute('pageTitle', $aPage['title']);
  25.  
  26. $oView->setAttribute('pageContent', $aPage['content']);
  27.  
  28. return $oView;
  29. }
  30.  
  31. public function isSecure()
  32. {
  33. return false;
  34. }
  35. }
  36. ?>


  1. <?php
  2. class PageModel
  3. {
  4. public function getPageByName($sPageName)
  5. {
  6. $sPageName = basename($sPageName);
  7.  
  8. $sPageFileName = _DIR_APPLICATION . 'pages/' . $sPageName . '.html';
  9.  
  10. if(is_readable($sPageFileName))
  11. {
  12. $aPage['title'] = null;
  13. $aPage['content'] = file_get_contents($sPageFileName);
  14.  
  15. return $aPage;
  16. }
  17. else
  18. return false;
  19. }
  20. }
  21. ?>


Mama nadzieje, ze troche pomoglem.

Adrian.
.rh-
Witam

Odgrzebuje temat, podpisuje się pod nim. Również zaczynam swoja przygodę z tym zagadnieniem, a nie chce zaczynać nowego topiku.

@Prph
Odnośnie rozmieszczenia katalogów.
W swoim mini projekcie mam katalog moduły, w którym zawieram podział na np.:
News, Products itp. W każdym z tych katalogów mam widok np (news_view, czy products_view, model (w skład modelu wchodzą dwie klasy ) ( 1- model reprezentuje u mnie klasa która jest odzwierciedleniem pól/kolumn bazy danych, 2 – klasa ze statycznymi metodami do zapisywania aktualizowania i pobierania danych itp. ) Widok to klasa która zawiera metody odpowiedzialne za konkretna akcje np.:
  1. <?php
  2. public function buildMenuTable() {
  3.  $rs = MenuMapper::getAll();
  4.  $this->tpl->setVar('rs', $rs);
  5.  return $this->tpl->fetch('menuTable.tpl.php');
  6. }
  7. ?>

A w pliku menuTable.tpl.php prezentacja danych...

Do tego mam jeden kontroler ktory zczytuje z url odpowiednie akcje i includuje odpowiednie pliki.

Czy rozwiązanie które zaprezentowałem kwalifikuje się na mini MVC (wiem ze takie cos nie istnieje...) ? Czy w dobrym kierunku idę ?

Pozdrawiam
Ociu
W mvc chodzi o to, aby moduły/akcje były podzielone teoretycznie na kontroler akcji, widok akcji i model akcji. Jak sobie zimplementujesz to Twoja osobista sprawa.
Prph
Ociu dobrze mowi smile.gif

Pamietaj, ze MVC to nie framework. MVC to tylko ideologia pisania aplikacji. Podam Ci zupelnie inny przyklad jego uzycia, a w pelni poprawny:

  1. <?php
  2. //index.php
  3. // Pokazuje dane o jakims uzytkowniku. Powiedzmy trzymane sa one w bazie.. no nie 
    wazne ;)
  4. // parametr id przekazywany jest w adresie.
  5.  
  6. $id = (int)$_GET['id'];
  7.  
  8. $oUzytkownik = new Uzytkownik($id);
  9. $sImieUzytkownika = $oUzytkoiwnik->getName(); 
  10.  
  11. $oSzablony = new Smarty(); // Przepraszam, ale dawno nie uzywalem smarty, nie wiem dokladnie jak go uzyc ;)
  12.  
  13. $oSzablony->assign('nazwa_uzytkownika', $sImieUzytkownika);
  14. $oSzablony->display('SzablonUzytownikow');
  15. ?>


  1. <!-- SzablonUzytkownikow.tpl -->
  2.  
  3. <h1>To strona o uzytkowniku</h1>
  4. <p>Uzytkownik ma na imie {$nazwa_uzytkownika}</p>


Nie ma zadnego frameworka, a jednak MVC. Uyztkownik jest modelem - zauwaz, ze powiedzialem, ze dane sa w bazie danych, ale jednak nie ma tu najmniejszego kodu, ktory na to wskazuje. Tak naprawde wie o tym tylko model. On sie laczy z baza danych (mysql, postrgesql, czy nawet plikami xml) i zwraca nam to, czygo szukamy.

Widok, to obiekt Smarty - systemow szablonow. Oczywiscie nikt nie kaze uzywac smarty (ja nie uzywam winksmiley.jpg).

Kontroler to index.php. Pobiera dane z $_GET, z modelu, przekazuje je do widoku i go wyswietla.

Adrian.
.rh-
Zgadza sie, pytam, gdyz czytajac wiele artykulow w pewnym momencie nie wiedzialem za co sie zabrac, a bardzo mi zalezalo na tym aby moj kod php byl tak obiektowy jak kod java:) odstawilem wiec czytanie i zabralem sie za pisanie...

Wiec wnioskuje ze to co napisalem w poprzednim moim poscie mialo "jakis" sens skoro nie zostalem obrzucony i sprowadzony do parteru:). Super.

Pozdrawiam!
thornag
Cytat(Helios @ 8.07.2006, 14:42 ) *
i wykonuje w nim akcje zmianu danych, a poniewaz akcja addUser() posiada plik konfiguracjny z wywolaniem jako kolejnej akcji countUsers wywoluje kolejna akcje. No i pozostaje wyswietlenie widoku


Pozwolilem sobie odgrzebac temat by zadac male pytanie. Ja postanowilem zaczac od czytania i zbierania wiedzy, ale wciaz jedna rzecz nie daje mi spokoju. Pliki akcji. Wszedzie gdzie czytam wyjasnione jest M V i C nie moge doczytac o akcjach. Z tego co jest podane wynika ze sa to jedne z najmniejszych niepodzielnych czynnosci, takie jak AddUser ModifyUser. Ok mozna przyjac ze akcja to wywolanie metody obiektu. Ale co z lancuchami i z plikami konfiguracyjnymi (z czego najbardziej nie zrozumiale sa dla mnie te drugie)? Co oznacza ze cos "posiada plik konfiguracjny z wywolaniem jako kolejnej akcji"

Bede wdzieczy za maly wyklad ewentualnie linki do zrodel gdzie bedzie to idiotoodpornie wytlumaczone.
Prph
Witam,

Akcja: dobrze rozumiesz czym jest. Akcja to po prostu realiacja jakiegos zadania. Np:
www.strona.pl?pokaz=galeria_fotografii. Z linku mozemy wywnioskowac, ze apliakcja php ma nam zaprezentowac galerie. To wlasnie galeria jest akcja. Tak samo moze byc akcja PokazNowosc, UsunUzytkownika.

Lancuchy akcji
Podczas jednego wywolania strony aplikacja php moze tak naprawde wykonac kilka kacji po kolei (czyli nastapi lancuch akcji). Jak? Oto przyklad:

Uzytkownik przeglada fotki na stronie. JEdna sie sie podoba, klika na UsunZdjecie.
Aplikacja php usuwa fotke z bazy lub z innego zrodla i powraca ponownie do wyswietlania fotek.
Jak to jest z poziomu aplikacji?

Zgloszenie: strona.pl/?akcja=UsunZdjecie&zdjecie=123.
Odczytuje id zdjecia (123), usuwa zdjecie
Uruchamia akcje PokazZdjecia. W efekcie uzytkownik odstaje fotki na ekranie, ale bez tej usunietej smile.gif.

To samo da sie realizowac przy pomocy redirect:

  1. <?php
  2. // plik z UsunZdjecie:
  3.  
  4. // usun z bazy fotke i wroc do prezentowania fotografii:
  5.  
  6. header('Location: <a href="http://strona.pl/?akcja=PokazZdjecia');" target="_blank">http://strona.pl/?akcja=PokazZdjecia');</a>
  7. exit;
  8. ?>


Zaleta lancucha akcji jest taka, ze strony nie trzeba przeladowac, wiec oszczedza sie czas smile.gif Efekt jest identyczny.

Konfiguracja i lancuchy akcji


Chyba chodzi o to, ze tworzony jest plik konfiguracyjny. znajduje sie w klatalogu configs/ i nazywa sie UsunZdjecie.php.

Aplikacja otrzymuje zgloszenie aby uruchimic akcje UsunZdjecie. Zna nazwe akcji i wie, ze tak samo ma nazywac sie konfig. Wiec wczytuje konfiga.

W konfigu moze byc podane: nastepna-akcja = 'PokazZdjecia'. Aplikacja wie, ze jak wykona akcje UsunZdjecie to ma wykonac PokazZdjecia.

UWAGA: to rozwiazanie jest raczej kiepskie. Lepiej w akcji zrobic metode "forward($nazwaAkcji, $parametry)" i po zakonczeniu danej akcji uruchamiac ja. CZesto zdarzy sie, ze bedziemy musieli wykonac inna akcje, bo nastapil jakis blad (np nie podano parametru id do usuniecia zdjecia.).

Pozdrawiam, Adrian.
thornag
Tak to wszystko miele i mam jeszcze kilka kolejnych pytan. Realizacja rejestrowania uzytkownika w frameworku opartym o wzorzec MVC. Kompletnie nie wiem z ktorej strony to ugryzc.

Dla przykladu. Zostaje wywolany URL http://www.domena.pl/view=RegistrationForm

Kontroller laduje widok RegistrationForm, jako ze nie ma modelu ,kontroller laduje defaultowy model np index. W modelu index metoda np Perform jest pusta (musi zostac zaimplementowana gdyz chcialbym zeby model dziedziczyl po abstrakcyjnej klasie model).

Kontroller laduje model, wywoluje pusta metode Perform modelu - nic sie nie zmienia.
Kontroller wywoluje metode Display() - zostaje wyswietlony formularz rejestracyjny.

Uzytkownik wypelnia formularz i klika w wyslij (walidacja po stronie przegladarki juz byla). I tutaj zaczynaja sie moje problemy.

Jak to wyglada dalej ? Mam sobie obiekt Request i w nim moge przeprowadzic walidacje po stronie serwera.

Ale jak to polaczyc dalej ?

Akcja formularz powiedzmy wyglada tak. http://www.domena.pl/model=User&action=AddNewUser

Kontroller laduje model User, i chce uruchomic akcje AddNewUser, i co dalej ?Ciagle potrzebuje walidacji bo nie wiem gdzie ja tutaj wcisnac, potrzebuje akcje w stylu User->setUsername($username), User->setAddress($address) itp, kiedy przelece przez wszystkie setCostam (powiedzmy ze walidacje ustawie w tych metodach), teraz musze wywolac Model->SaveUser() co powoduje zapisanie ustawionych pol do bazy danych. I teraz znow nie wiem co dalej, w tej akcji ustawic kolejna ktora ustawi widok na np RegistrationDone ?

Same tutaj problemy, powiedzmy ze poczawszy od metody setUsername zawiera ona instrukcje zeby kolejna wywolac setEmail() ta znowu setAddress() itp. Ale co jesli bede chcial wykonac zwykla operacje zmiany Addressu, ktora normalnie wygladala by tak.

  1. <?php
  2. $user = New User($id) // nastepuje ladowanie danych do wlasciwosci.
  3. $user->setAddress($newAddress);
  4. $user->Save();
  5. ?>


Jak sterowac takim dzialaniem za pomoca URL ? Gdzie tu wszedzie jest klasa Request ktora w gruncie rzeczy powstala u mnie po to zeby zajmowac sie calym I/O walidacja eskejpowaniem cytowaniem itp.

Ogolnie jak mowie naczytalem sie sporo ale nie potrafie tego do kupy poskladac.

Ten przyklad obslugi uzytkownika nurtuje mnie najbardziej, stad tez mam prosbe.

Biorac pod uwage nastepujacy StoryBoard :

Kod
1. Uzytkownik wchodzi na strone. Klika w "zarejestruj sie". Wypelnia formularz. Formularz nie zawiera bledow, uzytkownik widzi podziekowania. Uzytkownik jest na stronie glownej (zalogowany). Klika w profil. Chce zmienic swoj adres.

2. Uzytkownik wchodzi na strone. Klika w "zarejestruj sie". Wypelnia formularz. Formularz zawiera bledy, uzytkownik zostaje przekierowany na strone formularza(nie chodzi tutaj o informowanie co zrobil zle). Wypelnia jeszcze raz


Co do mojej prosby, moglby mi ktos opisac jak takie cos zrealizowac ( nie chodzi mi o to zeby to ktos zaimplementowal smile.gif), ogolnie taki Walkthrough na zasadzie:

Uzytkownik jest na stornei glownej mamy URL kontroller robi to tamto. Pozniej jest na stronie ?view=form (czy cos) kontroller robi to i tamto.

Wielkie dzieki za zainteresowanie.

@Prph Raz jeszcze dzieki, w koncu lancuchy staly sie klarowne w teori smile.gif
Prph
Witam,

Nie podoba mi sie u Ciebie organizacja MVC. Po pierwsze: strona.pl?model=Cos - zgloszenie moze zawierac jedynie akcje i parametry.

Uruchamiana jest akcja.
Akcja wie jakiego widoku uzyje i jakiego modelu uzyje.

Po drugie: nie kazda akcja potrzebuje modelu. Nawet polowa akcji nie wymaga modelu. Zobacz np. akcje DodajNowosc. Zadne dane nie pobierana sa z bazy (w naszym przykladzie). Akcja uzywa tylko widoku.

Bywa tak, ze akcja uzywa tylko modelu, widoku zas nie. Np: ZapiszUzytkownika.

Ko9lejna sprawa to uzywane kilku modeli w akcji. Zerknij:

  1. <?php
  2. // Akcja Pokaz zdjecia
  3.  
  4. $album = // pobierz id albumu do wyswietlenia z adresu url;
  5.  
  6. $oAlbym = new Model_Album($album);
  7. $id_autora = $oAlbum->getAuthor();
  8.  
  9. $oAutor = new Model_User($id_autora);
  10. echo 'Album nalezy do ' . $oAutor->getName();
  11. ?>


Nie mozesz wiec automatycznie ladowac widoku i modelu do akcji. Zrob klase bazowa dla akcji np. Action.
Kazda klasa akcji z niej dziedziczy.
Action posiada uzyteczne metody getModel($sModel), getView($sView). Kiedy potrzebujesz modelu/widoku po prostu piszesz w swojej akcji:

  1. <?php
  2. $oWidok = $this->getView('DodajUzytkownika');
  3. ?>


Co z walidacja?

Zajgorsza czesc aplikacji. Zawsze zajmuje najwiecej czasu i zawsze jest nudna winksmiley.jpg Nie zastanawialem sie jak zrobie to w nowymn frameworku, ale poprzednio mmialem cos w stylu:

  1. <?php
  2. // akcja DodajUzytkownia;
  3.  
  4. if(formularz nie przeslany) // czyli musimy go wyswietlin
  5. {
  6. $oView = $this->getView('DodajUzytkownika');
  7. $oView->display();
  8. return;
  9. }
  10.  
  11. // form przeslany, sprawdzamy dane:
  12.  
  13. $name = pobierz pole name z formularza;
  14.  
  15. $aErrors = array(); // tablica z komunikatami o bladach.
  16.  
  17. if(empty($name) || strlen($name) > 128)
  18. {
  19. $aErrors[] = 'Niepoprawna nazwa uzytkownika';
  20. }
  21.  
  22. // tu inne testy.
  23.  
  24. if(count($aErrors)) // czy wystapily jakies blady
  25. {
  26. $oView = $this->getView('DodajUzytkiownika');
  27. $oView->set('Errors', $aErrors);
  28. $oView->display();
  29. return;
  30. }
  31.  
  32. // tu odpalamy model i dodajemy uzytkiownika.
  33. // na koniec robimy:
  34.  
  35. $this->forward('PokazUzytkiownikow');
  36. ?>


Pozdrawiam, Adrian.
thornag
Hmm, duzo dalo mi to do myslania, tymbardziej ze przed chwilka mialem rozmowe ze znajomym programujacym w Javie. Do tej pory myslalem ze model odpowiedzialny jest za cala logike i to on steruje wszystkim. Z tego co zrozumialem z Twojego postu, nie bede sie upieral ze dobrze, wychodzi na to ze tak naprawde akcja jest plikiem wykonywalnym, ktora steruje i dobiera sobie i widok i model, ktory jak sadze zajmuje sie tylko przechowywaniem danych (takie kontener na dane).


Mamy plik index.php i url index.php?akcja=viewUser&id=4

Plik index.php includuje plik akcje/viewUser.php a w tym pliku mamy to wszystko o czym wspomniales czyli
tak naprawde na sztywno wpiety kod.
1. Zainicjowanie modelu/klasy User (tutaj wszystko sie wczytuje do wlasniciowsci obiektu);
2. Dodanie wlasciwosci User(username etc) do szablonu np smarty.
3. Display widok taki czy taki.

Jesli user chce zmienic swoje dane to zmienia formularz klika submit ktory prowadzi do index.php?akcja=modifyUser&id=4 i tutaj

1. Akcja inicjalizuje model User.
2. Wrzuca do niego zmienne POST
3. Zapisuje wszystko z bazie danych
4. Robi forward(viewUser) ktory robi to co opisane wyzej.

Jesli dobrze zrozumialem to mam dwa kolejne pytania. Jaka role ma w tym wszystkim kontroler ? Co on kontroluje. I co z obiektem User ktory po przekierowaniu z formularza zostal utworzony ponowanie z wszystkimi wlasciwosciami i zapisany. Czy po akcji modifyUser gdy wywoluje akcje viewUser mam ladowac dane do obiektu/modelu jeszcze raz ? Jak to rozwiazac ?


EDIT

Przeczytalem caly temat jeszcze z dwa razy i wyciagnalem troche dodatkowych informacji smile.gif Moje pojmowanie wyglada teraz tak.

Mamy request http://www.domena.pl/action=viewUser&userid=1.

W pliki index.php mamy (pseudokod)

  1. <?php
  2.  
  3. $oCtrl = New Ctrl();
  4.  
  5. $sAction = $oCtrl->getParam('action');
  6. $oAction = New $sAction();
  7. $oView = $oAction->Execute(); // tutaj akcja prosi o dane i wstawia je do "zmiennych szablonowych" i ustawia widok
  8. $oView->Display();
  9. ?>


Kontroler narazie zostawie, moja akcja viewUser

  1. <?php
  2. class viewUserAction extends Action {
  3. public function Execute() {
  4.  $oCtrl = Ctrl::getInstance();
  5.  $intUserId = $oCtrl->getParam('userid');
  6.  $oUser = New UserModel($intUserId); //model sam sobie pobiera dane wedlug podanego ID
  7.  $oView = $oCtrl->getView('viewUsers');
  8.  $oView->setVar('username', $oUser->getUsername());
  9.  return $oView;
  10. }
  11. }
  12. ?>


Teraz widok

  1. <?php
  2. class viewUserViewextends View {
  3.  public funtion __construct() {
  4. $oSmart = New Smarty();
  5. $oSmart->setTemplate('usersList.tpl') //to taa pseudo metoda tongue.gif ogolnie zeby bylo wiadomo co sie dzieje.
  6. public function setVar($name, $value) {
  7.  $oSmart->Assign($name, $value);
  8.  }
  9.  public function Display() {
  10. $oSmart->Display() // to tez taka pseudometoda :)
  11. }
  12. }
  13. ?>


Czy to ogolnie ma jakis sens ?
Ociu
Każdy sposób jest dobry, jeśli Ty uważasz, ze jest dobry. To jak ma działać Twój system to Twoja inicjatywa, a nie nasza. Jakby programiście mieli patrzyć, czy dobrze robią, nie powstały tak świetne frameworki jak mojavi, prado, symfony. Byłba by tylko jedna wytyczna: "Czy to wg. Was jest ok". Nie, to robimy tak, aby inni mieli dobrze. Tak to będzie istniał tylko jeden framework. Dlatego trzeba narzuć swój tok myślenia.

To było by tyle winksmiley.jpg
Saluto!, Wojtek
thornag
@Ociu No tak. Ale inni programisci mogliby stwierdzic np "o mlody w dobrym kierunku to idzie,mozna by powiedziec ze widzi sie tu wzorzec MVC, tylko to jakies takie malo elastyczne, pomysl co by bylo gdyby..." biggrin.gif
Jak to sie mowi po co wywazac otwarte drzwi, jesli ktos z gory widzi ze ten tok rozumowania jest bledny, bo to to to (a tu w konstruktorze lepiej to przekazac, a tu lepiej dziedziczyc bo costam), lepiej zeby opieprzyl mnie teraz niz zebym za jakis miesiac dwa moze wiecej odkryl smutna prawde ze cala praca poszla na marne bo od poczatku wychodzilem ze zlych zalozen.

@Prph
Cytat
actions/ - kontrolery akcji
models/ - modele
views/ - widoki
configurations/ - konfiguracje wszystkiego co zbudujesz na owym frameworku (np. akcji lub bibliotek, ktore bys mogl pozniej dodac.)


Mozesz wyjasnic co to sa kontrollery akcji a co jest w folderze configurations. Dalej mi to troche miesza.
I kolejne pytanie do Ciebie. Jesli w modelu wystepuje blad (np bledne zapytanie SQL) co wtedy robisz ? Wyrzucasz wyjatek ? jesli tak to jak go obslugujesz. Ja myslalem zeby uzyc do tego metody forward tylko mam problem z wymysleniem jak przekazac wiadomosc. Myslalem tez zeby w bloku Catch zawrzec instrukcje ktora mi bedzie ten wyjatek razem z mesgiem obslugiwala (np poprzez forward smile.gif).

I jeszcze jedno teoretyczne. Przypuscmy ze akcja ma za zadanie skontaktowac sie z modelem i zazadac od niego listy uzytkownikow. Lista jest pusta. Czy w tym przypadku najlepiej jest korzystac z (znowu) forward ? Na zasadzie if(!count($arUsers)) oCtrl->forward(jakas tam akcja).
Prph
Jak interpretowac termin kontroler, to zalezy jak napisany jest dany framework. Ponadto istnieje tzw FrontController - uruchamiany jako pierwszy i to on niby powinien odpalac akcje.

Ale akcja takze moze byc nazwana kontrolerem.

W Mojavi kontroler to GLOWNA czesc aplikacji. Ona rozbija adres url, wyciaga informacje o zgloszeniu. Ona odpala akcje i ona steruje aplikacja.

W Zend Framework kontroler to klasa zawierajaca akcje, np:

  1. <?php
  2. class KontrolerNowosci
  3. {
  4. publi function add();
  5. public function show(); // ble ble
  6. }
  7. ?>


Model jest odpowiedzialny za zapis, odczyt danych ze zrodla danych. A jakie jest zrodlo, to wie o tym tylko model. Chodzi o to, abys mogl pozniej wymienic model na inny i nie zmienic nawet jednej linii kodu w akcjach.

Co zrobic gdzy SQL sie wylozy? Moim zdaniem jest to niestandardowa sytuacja i tutaj nadaje sie wyjatek.
Lepiej niech aplikacja sie zatrzyma, niz ma dzialac z bladem.

Jak przechwycic?

  1. <?php
  2. //index.php - tzw plik bootstrap (bootujący)
  3.  
  4. require 'pliki z naszym frameworkiem';
  5.  
  6. try
  7. {
  8. $oFront = new FrontControler();
  9. $oFront->execute()
  10.  
  11. }
  12. catch(Exception $e)
  13. {
  14. //no i mamy ;)
  15. echo $e->getMessage();
  16. }
  17. ?>


Forward to zle rozwiazanie. A co jezeli wyjatek wystapi podczas uruchamiania samego frameworka?
Aplikacja bedzie w kólku i z niego nie wylezie :/
Poza tym - forward na nic sie nie przyda. Raczej redirect.

Kiedy juz troche poczytasz o MVC i frameworkach, polecam pobrac Zend Framework i poczytac http://framework.zend.com/manual/pl/index.html - Bardzo dobra dokumentacja, z ktorej wiele sie nauczysz.

Adrian.
bim2
Przeczytałem temat i teraz ja zadam pare pytań tongue.gif. Troszke juz rozumiem o co chodzi ale jest pare niedogodności.

index.php
  1. <?
  2. define('DIR_ACTION', 'actions/');
  3. define('DIR_MODEL', 'models/');
  4. define('DIR_VIEWS', 'views/');
  5. define('DIR_CLASS', 'class/');
  6.  
  7. class Control
  8. {
  9. private $Request=false; // obiekt
  10. public $action; // nazwa akcji - nieobowiazkowa
  11. private $view; // nazwa widoku
  12. protected $model; // nazwa modelu - nieobowiazkowa
  13.  
  14. protected $objView; // obiekt widoku
  15. public $objModel; // obiekt modelu
  16.  
  17. function __construct($param)
  18. {
  19.  
  20.  
  21. $this->view = $param->getParam('view');
  22. $this->view = ($this->view) ? $this->view : 'news';
  23.  
  24. $this->model = ($param->getParam('model')) ? $param->getParam('model') : $this->view;
  25. $this->model .= 'Mod';
  26.  
  27. $this->action = $param->getParam('action');
  28. $this->action .= ($this->action) ? 'Action' : 'defaults';
  29.  
  30.  
  31.  
  32. if(file_exists(DIR_MODEL.$this->model.'.php'))
  33. {
  34. require_once(DIR_MODEL.$this->model.'.php');
  35. $this->objModel=new $this->model($this);
  36. if(!empty($this->action))
  37. {
  38.  
  39. if(!method_exists($this->objModel, $this->action))
  40. {
  41. require_once(DIR_CLASS.'error.class.php');
  42. $error = new Error;
  43. if(!method_exists($error, 'NieZnaleziono'))
  44. {
  45. echo 'error';
  46. }
  47. else
  48. {
  49. $error->NieZnaleziono($this);
  50. }
  51. }
  52. else
  53. {
  54. $action=$this->action;
  55. $this->objModel->$action($this);
  56. }
  57. }
  58.  
  59. }
  60.  
  61. }
  62.  
  63. public function execute($action){
  64.  
  65. // laduje obiekt widoku
  66. require_once(DIR_VIEWS.$this->view.'.view.php');
  67. $this->objView=new $this->view;
  68. $this->objView->$action($this->objModel);
  69.  
  70. }
  71.  
  72. }
  73. class Router
  74. {
  75. function getParam($name_param, $typ='get')
  76. {
  77. return $_GET[$name_param];
  78. }
  79. }
  80. $router = new Router;
  81.  
  82. $ctrl = new Control($router);
  83. ?>


models/newsMod.php
  1. <?php
  2. class newsMod {
  3. var $query;
  4. var $true;
  5.  
  6. function defaults($param) 
  7. {
  8.  
  9. $this->query='Testowy news';
  10. $param->execute('show');
  11. }
  12. function add()
  13. {
  14. echo 'dodaje newsa';
  15. }
  16.  
  17. }
  18. ?>

i
views/news.view.php
  1. <?php
  2. class news {
  3. function __construct()
  4. {
  5.  
  6. }
  7. function show($model)
  8. {
  9. echo 'lol';
  10. echo $model->query;
  11. }
  12. }
  13. ?>

I teraz pare pytań. Co ma robic akcja i jak to ma wyglądać. teraz mam że akcja wywołuje metode w modelu, ale chyba nie o to chodzi? Jak mam trzymac akcje? Tzn. ma byc w pliku tak jak modeli i widok czy kontroler ma ja obsłużyć?
thornag
@prph korzystajac z Twojej zyczliwosci a przedewszystkim cierpliwosci i dobrych rad postanowilem w koncu cos splodzic. No i wyglada to tak.

Controller
  1. <?php
  2. class Controller {
  3.  
  4. protected $sAction;
  5.  
  6. protected $oRequest;
  7.  
  8. protected $sDefaultAction = 'Index';
  9.  
  10. protected $sView;
  11.  
  12. protected $sDefaultView = 'Index';
  13.  
  14. protected $aVars = array();
  15.  
  16. public function __construct() {
  17. $oRequest = New WebRequest();
  18. }
  19.  
  20. static function & getInstance() {
  21. return $this;
  22. }
  23.  
  24. public function forward($sAction) {
  25. $this->sAction = $sAction;
  26. $this->Perform();
  27. }
  28.  
  29. public function getAction($sAction = null) {
  30. $this->sAction = empty($sAction) ? $this->sDefaultAction : $sAction;
  31. }
  32.  
  33. public function getRequest() {
  34. return $this->oRequest;
  35. }
  36.  
  37. public function getView($sView = null) {
  38. $this->sView = empty($sView) ? $this->sDefaultView : $sView;
  39. }
  40.  
  41. public function setVariable($value, $key = null) {
  42. $this->aVars[$key] = $value;
  43. }
  44. public function Perform() {
  45. $sActionPath = _PATH_ACTION.'actions.'.$this->sAction.'.php';
  46. require_once(_PATH_LIB.'class.Action.php');
  47.  
  48. if (!file_exists($sActionPath)) {
  49.  
  50. $this->forward("ActionDoesntExists");
  51.  
  52. } else {
  53.  
  54. require_once($sActionPath);
  55. }
  56. $oAction = New $this->sAction();
  57. $oAction->Execute();
  58. return;
  59. }
  60.  
  61. public function Display() {
  62. $sTemplatePath = _PATH_TEMPLATE.'views.'.$this->sView.'.php';
  63. require_once(_PATH_LIB.'class.View.php');
  64.  
  65. if (!file_exists($sTemplatePath)) {
  66. $this->forward("ViewDoesntExists");
  67. } else {
  68. require_once($sTemplatePath);
  69. }
  70. $oView = New $this->sView();
  71. $oView->Assign(& $this->aVars);
  72. $oView->Parse();
  73. }
  74.  
  75. }
  76. ?>


Przykladowy widok

  1. <?php
  2. abstract class View {
  3.  
  4. protected $oSmarty;
  5.  
  6. public function __construct() {
  7. $this->oSmarty = New Smarty();
  8. }
  9.  
  10. public function Assign(& $aVars) { 
  11. foreach ($aVars as $key => $value) {
  12. $this->oSmarty->Assign($key, $value);
  13. }
  14. }
  15.  
  16. abstract function Parse() {}
  17. }
  18.  
  19.  
  20. class ActionDoesntExists extends View {
  21.  
  22. public function Parse() {
  23. $oSmarty->setTemplate('path/template');
  24. $oSmarty->Display();
  25. }
  26. }
  27.  
  28. ?>


I akcja

  1. <?php
  2.  
  3. abstract class Action {
  4.  
  5. protected $oController;
  6.  
  7. public function __construct() {
  8. $this->oController = Controller::getInstance();
  9. }
  10.  
  11. abstract function Execute() { }
  12. }
  13.  
  14.  
  15.  
  16. class ActionDoesntExists extends Action {
  17.  
  18. public function Execute() {
  19. $oController->getView(get_class($this));
  20. }
  21. }
  22. ?>


EDIT:
I wywolanie
  1. <?php
  2.  
  3.  
  4. $Application = New Controller();
  5. $Application->getAction($Application->getRequest()->getParam('action', Request::GET));
  6. $Application->Perform();
  7. $Application->Display();
  8.  
  9. ?>

EDIT END

Zaczalem wczoraj tak na dziko troche, fakt faktem tak jak pisales zdaje sobie sprawe z tego ze aplikacja moze sie zapetlic wiec musze dodac jeszcze jakies wyjatki i obsluge tych bledow, no chyba ze zalozenie ze akcja ActionDoesntExists i ViewDoesntExists i odpowiadajace jej widoki sa zawsze smile.gif Ale jak to mowia lepiej dmuchac na zimne smile.gif

Ogolnie Prph, czy zrealizowalem ogolne zalozenia MVC tym kodem ?

Jesli tak to oczywiscie zdaje sobie sprawe z tego ze to pierwszy framework i w miare budowania na nim aplikacji bede wpadal na nowe i (mam nadzieje) lepsze pomysly. Zalezy mi tylko na jakims komentarzu i stwierdzeniu wprost czy moj start jest zgodny czy nie zgodny z zalozeniami smile.gif

P.S jeszcze nie testowalem, dzisiaj napisze klase Request i Abstrakcje dla DB i jakis model. smile.gif
bim2
Thormag, powiem ci że nakierowałes mnie smile.gif Kod mi sie podoba, ale jak narazie ja tez nie dokońca wiem czy to ma tak wyglądać biggrin.gif Czekamy na odpowiedź

Poczytałem torszkę o MVC (przyklejony temat) i juz conieco rozumiem. Trzeba to tko sensownie napisać.

Mamy Kontroler który parsuje URL(np. klasą router) i uruchamia daną akcję. Akcja natomiast jeśli chce (nie musi) uruchamia model. Model zas uruchamia widok. A teraz np. jeśli damy action=AddNewsForm to akcja nie poprosi modelu a da nam odrazu widok. Czy o to chodzi? Prosze jakiegoś speca o odpowiedź czy dobrze rozumuje?
thornag
Z tego co zrozumialem model nie ustawia widoku. Model to taki kontener na dane, jedna tabela w bazie danych (bez kluczy obcych) jeden model (czy tam GenericObject) Model pobiera dane i je oddaje, jak to juz nikogo nie obchodzi jego sprawa. U mnie tam w tym czyms co niekoniecznie musi byc MVC dziala to tak ze model sobie pracuje w sumie w oderwaniu od reszty. Akcja go uruchamia, akcja prosi o dane, jak je ma to analizuje i w zalezosci od tego co model zwrocil (moze nic nie zwrocic bo tabela pusta) ustawia odpowiedni widok, albo wykonuje kolejna akcje.
Ludvik
Trochę zbyt sztywno trzymacie się powiązania modelu z klasami... Otóż model, to dane oraz ich zachowania... Model może być jeden, ale sposobów dostępu do niego może być wiele. Zmiana modelu to zmiana danych (czy ich zachowań), a nie klasy dostępowej... W końcu na model składają się też działania wykonywane w akcjach na danych. Zawsze kojarzyłem model z pojęciem abstrakcyjnym, którego raczej nie można przełożyć na jedną klasę.

Takie przynajmniej jest moje zdanie. Jak się pomyliłem, to chętnie posłucham, jak inni to widzą smile.gif
bim2
Mhh, dobra to może teraz cos takieog pokaże. Fajnie działa:
index.php
  1. <?
  2. define('PATH_ACTION', 'actions/');
  3. define('PATH_MODEL', 'models/');
  4. define('PATH_VIEW', 'views/');
  5. define('PATH_CLASS', 'class/');
  6. define('PATH_LIB', 'libs/');
  7. $conn = mysql_connect('localhost', 'root', '');
  8. mysql_select_db('nfs_new', $conn);
  9. class Controler {
  10. public $objAction; //objekt akcji
  11. public $action; //akcja
  12. private $defaultAction = 'index'; //domyślna akcja
  13. public $objMod;
  14. public $model;
  15. public $objViewC;
  16. public $objView;
  17.  
  18. public $router;
  19. public $oldAction;
  20. public $getView;
  21. public $view;
  22.  
  23. function __construct($router)
  24. {
  25. $this->router = $router;
  26. $this->action = $router->getString('action');
  27. $this->view = $this->router->getString('view');
  28. }
  29. function & getInstance()
  30. {
  31. return $this;
  32. }
  33. function getAction()
  34. {
  35. return $this->action = ($this->action) ? $this->action : $this->defaultAction;
  36. }
  37. function setAction($action='')
  38. {
  39. $this->action = $action;
  40. $this->perfom(true);
  41. }
  42. function setView($view='')
  43. {
  44. $this->view = ($view) ? $view : 'defaults';
  45. $this->perfom();
  46. }
  47. function getView()
  48. {
  49. return ($this->view) ? $this->view : 'defaults';
  50. }
  51. function perfom($doesntAction=false)
  52. {
  53. $action_path = PATH_ACTION.$this->getAction().'.action.php';
  54.  
  55. if(!file_exists($action_path))
  56. {
  57. if(!$doesntAction)
  58. {
  59. $this->oldAction = $this->getAction();
  60. $this->setAction('ActionDoesntExists');
  61. return;
  62. }
  63. else
  64. {
  65. echo 'Nie można znaleĽć '.$this->action;
  66. return;
  67. }
  68. }
  69. else
  70. {
  71. if(!is_object($this->objAction))
  72. {
  73. require_once $action_path;
  74. $act = $this->getAction();
  75. $this->objAction = New $act($this);
  76. }
  77. $gview = $this->getView();
  78. $this->objAction->$gview($this);
  79.  
  80. }
  81. }
  82. function display()
  83. {
  84. if(!is_object($this->objViewC))
  85. {
  86. require_once PATH_LIB.'view.lib.php';
  87. $this->objViewC = new View();
  88. }
  89. return $this->objViewC;
  90. }
  91.  
  92. function model()
  93. {
  94. $this->model = $this->getAction().'Mod';
  95. $path = PATH_MODEL.$this->getAction().'.model.php';
  96. if(!is_object($this->objMod))
  97. {
  98. if(!file_exists($path))
  99. {
  100. $this->setAction('ModelDoesntExists');
  101. return;
  102. }
  103. else
  104. {
  105. require_once $path;
  106. }
  107.  
  108. $this->objMod = new $this->model($this);
  109. }
  110.  
  111. return $this->objMod;
  112.  
  113. }
  114.  
  115. function view()
  116. {
  117. $this->view = $this->getAction().'View';
  118. $path = PATH_VIEW.$this->getAction().'.view.php';
  119. if(!is_object($this->objView))
  120. {
  121. if(!file_exists($path))
  122. {
  123. $this->setAction('ViewDoesntExists');
  124. }
  125. else
  126. {
  127. require_once $path;
  128. }
  129.  
  130. $this->objView = new $this->view($this);
  131. }
  132.  
  133. return $this->objView;
  134.  
  135. }
  136.  
  137. }
  138. class Router
  139. {
  140. function getString($name_param, $typ='get')
  141. {
  142. return (string) $_GET[$name_param];
  143. }
  144. }
  145. $router = new Router;
  146.  
  147. $ctrl = new Controler($router);
  148. $ctrl->perfom();
  149. ?>


libs/view.lib.php
  1. <?
  2. class View {
  3. private $Assign;
  4. function assign($assign)
  5. {
  6. foreach ($assign as $key => $value) 
  7. {
  8. echo $key.'= '.$value.'<hr>';
  9.  
  10. } 
  11. }
  12. function fetch($plik)
  13. {
  14. return $this->Assign;
  15. }
  16. }
  17. ?>

models/index.model.php
  1. <?
  2. class IndexMod {
  3. public $query;
  4. public $ctrl;
  5. function __construct($ctrl)
  6. {
  7. $this->ctrl = $ctrl;
  8. }
  9. function defaults()
  10. {
  11. $q=mysql_query("SELECT * FROM new_news");
  12. while($r=mysql_fetch_assoc($q))
  13. {
  14. $news[$r['news_id']]['tytul']=$r['news_tytul'];
  15. $news[$r['news_id']]['text']=$r['news_tekst'];
  16.  
  17. }
  18. $this->query = $news;
  19. /*$view = $cont->display();
  20. $view->assign(array('lol' => 'lolek'));
  21. echo $view->fetch('jakis_plik');*/
  22. }
  23. function news()
  24. {
  25. if($this->ctrl->router->getString('id'))
  26. {
  27. $q=mysql_query("SELECT * FROM new_news WHERE news_id='".$this->ctrl->router->getString('id')."'");
  28. $news['tytul']=$r['news_tytul'];
  29. $news['text']=$r['news_tekst'];
  30. $this->query = $news;
  31. }
  32. else
  33. {
  34. $this->ctrl->setView();
  35. }
  36. /*$view = $cont->display();
  37. $view->assign(array('lol' => 'lolek'));
  38. echo $view->fetch('jakis_plik');*/
  39. }
  40. }
  41. ?>

views/index.view.php
  1. <?
  2. class IndexView {
  3. public $query;
  4. function __construct($ctrl)
  5. {
  6.  
  7. }
  8. function defaults($mod)
  9. {
  10. $views = $mod->ctrl->display();
  11. foreach($mod->query AS $val)
  12. {
  13. $views->assign($val);
  14. }
  15.  
  16. echo $views->fetch('rrf');
  17. /*$view = $cont->display();
  18. $view->assign(array('lol' => 'lolek'));
  19. echo $view->fetch('jakis_plik');*/
  20. }
  21. function news_one($mod)
  22. {
  23. $views = $mod->ctrl->display();
  24. $views->assign($mod->query);
  25.  
  26. echo $views->fetch('rrf');
  27. }
  28. }
  29. ?>

no i ostanie
actions/index.action.php
  1. <?
  2. class Index {
  3. function __construct($ctrl)
  4. {
  5.  
  6. }
  7. function defaults($ctrl)
  8. {
  9. $mod = $ctrl->model($ctrl);
  10. $mod->defaults();
  11. $widok = $ctrl->view();
  12. $widok->defaults($mod);
  13.  
  14. }
  15. function news($ctrl)
  16. {
  17. $mod = $ctrl->model($ctrl);
  18. $mod->news();
  19. $widok = $ctrl->view();
  20. $widok->news_one($mod);
  21.  
  22. }
  23. }
  24. ?>


Czy jest juz na lepszej drodze? Powiem tlyo że to działa ?view=news&id=1 lub jak podasz tylko view=news to przejdzie do defaults() winksmiley.jpg Jestem na dobrej drodze? Prosze powiedzieć prosto z mostu. "TAK" lub "NIE" biggrin.gif
thornag
@Ludvik Czyli reasumujac i po ludzku mozna by powiedziec ze akcja i kontenery na dane to model i tyle. W sumie by sie zgadzalo, kontroller wywoluje akcje ktora jest modelem ta pracuje z jakimis danymi za posrednictwem jakis innych klas dostepowych czy tez klas przechowywujacych dane (ktore jak to mowilismy tez s amodelem). Wracajac do poczatku poprzedniego zdania z powodzeniem mozna zamienic "kontroller wywoluje akcje" na "kontroller wywoluje model". Teraz juz mi jasniej to wyglada dlaczego w miniFrameworku autorstwa Hwao w komentarzach jest ze tu a tu wywoluje on model a wygladalo dla mnie jak akcja smile.gif W koncu akcja tez model smile.gif

A tak zupelnie na boku to po tym jak wczoraj splodzilem ten zalazek to strasznie mi brakowalo tego modelu, model tylko przechowywanie danych ? Zastanawialem sie wtedy dlaczego wzorzec sie nazywa MVC a nie AVC smile.gif No teraz juz wiem (chyba).

@bim2 Teraz jak tak to wszystko czytam to sobie mysle ze czas wrocic do poczatkow tego tematu i wypowiedzi mowiacych o tworzeniu frameworka zeby byl wygodny dla Ciebie i ze tak naprawde MVC to jedynie koncepcja ktora kazdy realizuje po swojemu. Mam zamiar zbudowac kilka aplikacji na tym moim mini monstrum, jak pisal Hwao napewno wtedy wyjda bledy i inne koncepcje. Poki masz dane osobno tak ze mozesz wymieniac ich zrodlo z moze malutkimi zmianami kosmetycznymi, poki widoki i layouty pracuja w oddaleniu od logiki to chyba wszystko w porzadku bo jak sie nie myle podstawowa koncepcja MVC to odziel wizualnosc od funkcjonalnosci smile.gif
Ludvik
Żeby rozwiać wątpliwości - blueprints mvc. Sam w dyskusjach staram się nie używać słowa model - wydaje mi się trochę sztuczne... smile.gif Wywołujemy akcje, dane pobieramy z bazy (poprzez DAO), operacje wykonujemy na danych. Wszystko to należy do modelu, a jednak można uniknąć tego słowa smile.gif

Potęga wzorców projektowych tkwi właśnie w tym, że nie są ograniczone implementacją smile.gif Jedyne czego wymaga wzorzec MVC to oddzielenie warstwy prezentacji od logiki aplikacji i danych. To w jaki sposób to osiągniesz, to Twoja sprawa. Oczywiście w większości frameworków widujemy podobne implementacje wzorców Front Controller, Intercepting Filter itp... Jest to związane z praktycznością tych wzorców oraz ze ścisłym pozwiązaniem ich z MVC.
bim2
@thornag: Masz racje. Każdy robi MVC tak jak chce smile.gif byle zrobic z tego MVC. winksmiley.jpg Dla mnie to jest MVC. Przypomniałem sobie jak mam zrobione komentarze w swoim systemie. Musze przeklejac kod pobierania newsów smile.gif, a tu wywołam tylko akcje news setAction('news') ;P Wydaje mi się to super

@Ludvik: Masz całkowita racje. Już ktoś na początku podawał. Że samo include('moduly/'.$mod.'.php'); i tam masz pobieranie z bazy i smarty, to też MVC, tylko troszkę inne winksmiley.jpg
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.