Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MVC] Kontroler - gdzie?
Forum PHP.pl > Forum > PHP > Object-oriented programming
Kikert
Witam,
uprzedzam, że przeczytałem temat przypięty wraz z odnośnikami i niewiele mi to pomogło - niestety.

Mam trzy pytania odnośnie tego wzorca - jeżeli tworzę aplikację web'ową, to:
1. Czy kontroler jest samym plikiem (index.php), czy dopiero plik główny go inicjuje?
2. Jak jest z widokiem? Czy HTML jest zwracany do kontrolera, czy do pliku głównego? (przy opcji, że kontroler trzeba wcześniej załączyć)
3. Czy widok jest załączany przez kontroler, czy przez plik główny? (również przy drugiej opcji)
bełdzio
ad1. index.php to bootstrap, czyli plik, który odpowiada za ustawienie aplikacji tzn dołączenie potrzebnych bibliotek etc oraz odpalenie kontrolera, który został wywołany
ad2. widok zwracany jest użytkownikowi, czyli najpierw odpalany jest bootstrap, który ładuje odpowiedni kontroler, kontroler pobiera dane z modelu i wysyła je do widoku, widok składa wsio w całość i prezentuje userowi
ad3. przez kontroler
Kikert
OK, jeszcze jedno pytanie (ad2.) - jak to wygląda? Bo kontroler jest klasą, która wywołuje następną klasę (jeżeli dobrze rozumiem). I jak wtedy z widoku przekazać cokolwiek do bootstrapa?
blooregard
Widok juz nic nigdzie nie przekazuje, wywołuje jedynie metodę np. show(), która daje na wyjście gotowy HTML.
Kikert
Czyli bootstrap inicjuje kontroler, kontroler moduły, a na końcu widok, który korzysta np. z echo?
Mephistofeles
Sprawdź sobie jak to robią popularne frameworki.
webdice
Masz model, kontroler i widok. Kontroler pobiera dane z modelu i przekazuje do widoku, a jak sobie to zaprojektujesz to już Twoja sprawa. Możesz obsługiwać żądania w indexie, a możesz napisać front controller, router, dispatcher itp.
Zyx
Kontroler nie przekazuje żadnych danych z modelu do widoku. We wzorcu MVC widok jest sam zobligowany je pobierać z modelu, a przesyłanie ich przez kontroler to wymysł twórców Ruby On Rails i podobnych pionierskich frameworków, którzy źle spojrzeli na diagram i co później zostało powielone w milionach egzemplarzy jako obowiązujący dogmat. Nawiasem mówiąc jest to jeden z głupszych pomysłów, bo taki pseudo-MVC nie różni się praktycznie niczym od pisania kodu ciurkiem, gdzie skrypt najpierw sobie pobiera dane z bazy, a później wstawia je w szablon, tyle że w "profesjonalnych frameworkach" pobieranie z bazy nazwano Modelem, szablon Widokiem, a resztę Kontrolerem i dlatego jest to "profesjonalne".
blooregard
Kurczę, Zyx, teraz żes mnie zastrzelił sad.gif

http://www.ploug.org.pl/szkola/szkola_5/ma...ly/5_Struts.pdf
Czyli prawidłowo skonstruowana architektura MVC powinna wyglądać tak:

- index.php ładuje kontroler (nazwijmy go akcja01)
- kontroler akcja01 ładuje model akcja01, a ten z kolei tworzy sobie obiekt widoku akcja01
- kontroler akcja01 wywołuje dzialanie01, na podstawie akcji usera (np. kliknięcie na link index.php?akcja=01&dzialanie=01 )
- model realizuje dzialanie01, generuje wyniki i przekazuje je do widoku akcja01, który wyswietla je w miejscu przeznaczonym na rezultat wykonania dzialanie01.

Czyli róznica polega na tym, że model gotowych wyników dzialania01 nie zwraca juz do kontrolera, a ten dopiero przekazuje ten wynik do widoku, ale od razu wynik dzialania01 idzie z modelu do widoku, tak?
Zyx
Mniej więcej właśnie o to chodzi. Architektura MVC dla aplikacji WWW (tzw. Model 2) wygląda następująco. Mamy dwa scenariusze:

Użytkownik chce coś zobaczyć

Kontroler:
- Sprawdza, co zrobił użytkownik
- Wybiera odpowiedni widok
- Wybiera odpowiedni model
- Informuje widok, z jakiego modelu będzie korzystać.

Model
- Pobiera dane na żądanie widoku

Widok
- Decyduje o tym, jak wyświetlić dane
- Pobiera interesujące go dane z modelu
- Zajmuje się obsługą logiki wyświetlania
- Wyświetla wszystko

Użytkownik chce coś zmienić (formularz)

Tutaj w stosunku do klasycznego MVC jest taka modyfikacja, że dane przychodzą do nas w żądaniu HTTP jako pewne zadanie dla kontrolera.

Kontroler
- Sprawdza, co użytkownik zrobił.
- Wybiera model.
- Wybiera widok, jeśli potrzeba, albo robi redirect, co technicznie oznacza, że inny kontroler rozpoczyna pracę.
- Pobiera dane i przekazuje je do modelu z żądaniem zmiany stanu (czyli np. aktualizacja danych w bazie).
- Informuje widok, z jakiego modelu ma korzystać.

Model
- Zmienia swój stan, czyli dokonuje aktualizacji informacji.
- Udostępnia dane.

Widok
Nie ma bata, w HTTP albo robimy przekierowanie, czyli skaczemy do innego kontrolera, albo musimy coś wyświetlić, dlatego widok dalej działa tak samo.

Zasadniczo w klasycznym MVC wmieszany jest jeszcze wzorzec obserwatora na wypadek, gdyby model samoistnie zmienił stan (wtedy może on powiadomić widok, że coś się zmieniło i trzeba odświeżyć ekran), jednak w WWW nie ma to żadnego sensu praktycznego ze względu na budowę protokołu HTTP, dlatego się to pomija. Zauważmy też, że część komunikacji między komponentami realizowana jest za pomocą wywołań odpowiednich metod, a część (np. widok informuje kontroler, że coś się stało) realizowana jest za pomocą żądań HTTP.

Dodatkowo należy pamiętać jeszcze o dwóch kretynizmach popełnianych we frameworkach:
- Zrównanie modelu z ORM-em. ORM może być wykorzystywany przez model, ale nie może być modelem, bo nie i koniec. Model ma stanowić abstrakcyjny interfejs dostępowy tak, by aplikacja nie musiała się zajmować tym, czy dane idą z bazy czy z plików czy z czegoś innego. Tymczasem we współczesnych frameworkach z technicznego punktu widzenia jeśli będziemy chcieli coś pobrać z czegoś innego niż baza, to pozbawiamy się modelu. Przykład problemu, który to powoduje: mamy jakieś teksty informacyjne wyświetlane w różnych miejscach strony, które zapisane są na sztywno w jakimś pliku. Aplikacja jest rozbudowywana, pojawia się możliwość wprowadzania artykułów i klient chciałby, by w ramach tego mógł też edytować te statyczne teksty. I nagle okazuje się, że zmienia się wewnętrzna reprezentacja danych, a my żeby ją uwzględnić, zmieniamy... kontroler.

- Zrównanie szablonów i systemów szablonów z widokiem. No hola hola, a gdzie logika prezentacji? Przecież jak mamy np. stronicowanie, to gdzieś musimy je także skonfigurować, coś się musi zająć obsługą techniczną tego stronicowania, ale ponieważ widok jest szablonem, kod leci do... kontrolera. Coś tu nie gra, kontroler przecież nie powinien zajmować się tym, jak dane są prezentowane, a według mnie obecność stronicowania to specyfika ustaleń między widokiem, a modelem.

Poniżej przykład, jak można w takim modelu MVC zbudować coś fajnego. Przyjrzyjmy się CRUD-owi, czyli klasycznemu zestawowi operacji bazodanowych. Mamy listy elementów: newsy, artykuły, użytkowników itd. W "pseudo-MVC" głoszonym przez współczesne frameworki PHP tzw. "szybkość i prostotę tworzenia" uzyskuje się nie za pomocą "pseudo-MVC", tylko narzędzia konsolowego, które automatycznie generuje nam 483827834738 plików, po jednym dla każdej tabeli i które potem musimy ręcznie wypełniać. Tymczasem w prawdziwym MVC możemy zastosować takie podejście:

- Tworzymy widok ListView, który pobiera dane z modelu, opakowuje je w listę, dodaje sortowanie po kolumnach i stronicowanie.
- Autorytarnie stwierdzamy, że widok ListView może współpracować z modelami implementującymi interfejsy Listable, Sortable, Paginable, ListDefinitions
- Za pomocą zawartych w tych interfejsach metod widok pobiera z modelu listę elementów, pobiera informacje o tym, które elementy można sortować, przekazuje informacje o tym, jaka strona wyników go interesuje, zaś przy pomocy ListDefinitions może ściągnąć informacje o tym, jak np. zatytułować kolumny, jak nazywają się wyświetlane byty itd.
- Tworzymy 298373 modeli implementujących te interfejsy, każdy pobiera dane ze swojej tabelki i odpowiednio reaguje na wywołania metod w tych czterech interfejsach.

Różnica jest kolosalna. Jeśli w takim Zend Frameworku czy innym nagle stwierdzimy, że chcemy wzbogacić interfejs o np. wyszukiwanie, jesteśmy w d..., bo musimy to dopisać z osobna do każdego kontrolera, każdego modelu i każdego widoku dla każdej tabeli. Tutaj dodajemy kolejny interfejs, zmieniamy JEDEN widok, a reszta to poprawki w modelach. O ileż mniej roboty? O ileż większa zgodność z zasadami projektowania obiektowego? Powiem nawet więcej - widok może być inteligentny i posprawdzać sobie, jakie interfejsy implementuje model i na podstawie tego decydować: "aaa, ten model nie implementuje Paginable, więc oznacza to, że tu nie ma być stronicowania". I nagle okazuje się, że możemy diametralnie zmienić funkcjonalność, po prostu dodając lub zabierając interfejsy z modeli. Oczywiście jak piszemy front-end i sztywne ramy mechanizmu CRUD nam nie pasują, musimy napisać inne widoki do konkretnych zastosowań, ale w wielu przypadkach nawet te konkretne zastosowania są na tyle ogólne, że można stworzyć jeden widok pasujący do kilku miejsc i sytuacji. Tak się składa, że robiłem niedawno aplikację w PHP opartą o prawdziwy wzorzec MVC i to, co serwują nam frameworki, nawet do pięt mu nie dorasta.

Ironią jest, że jedyny znany mi skrypt poprawnie implementujący MVC to... Joomla. I to jest chyba jedyna dobra rzecz, jaką można powiedzieć o jej kodzie.

Jakby ktoś jeszcze nie dowierzał, to podaję pierwszą z brzegu książkę prezentującą właśnie taki sposób działania MVC w aplikacjach WWW, z widokiem komunikującym się bezpośrednio z modelem: Head First Design Patterns, strony 567-575.
Kikert
Ciekawa dyskusja się tutaj wywiązała, ale jako laik liczyłbym na jakąś zgodną myśl.

Ciekawa dyskusja się tutaj wywiązała, ale jako laik liczyłbym na jakąś zgodną myśl.
blooregard
@Zyx, dziękuję Ci bardzo za wyjaśnienie. W wolnej chwili, jeśli masz takowe, czy mógłbyś zamieścić parę linków do jakiś bardziej szczegółowych opisów tematu? Oczywiście nie omieszkam poszukać, ale może masz coś godnego uwagi, a trudnego w wygooglowaniu.

batman
@Zyx
Wszystko ładnie pięknie, ale to tylko teoria. A jak wiadomo od teorii do praktyki droga daleka. Implementacja MVC w "nowoczesnych" frameworkach, nie jest jakąś tam fanaberią kilku programistów, którzy zapragnęli być pionierami, tylko dobrze przemyślany wybór sztabu ludzi. Przy projektowaniu jakiegoś rozwiązania należy wziąć pod uwagę przede wszystkim koszt*. Jeśli coś można zrobić taniej (co nie znaczy, że gorzej), to dlaczego tego z takiej możliwości nie skorzystać?
Ślepe trzymanie się teoretycznych rozważań nie przyniesie nic dobrego. Spowoduje jedynie, że czas wykonania projektu znacząco się wydłuży, a niektóre funkcjonalności nie zostaną wdrożone, ponieważ "tak nie wolno".

W prawdziwym świecie MVC oznacza:

M - model, czyli klasa/zestaw klas operujących na danych. W projektach, które w rozwoju nie mają zaplanowanej migracji na inne źródło danych lub dodanie nowego źródła danych, mogą bezpośrednio na tym źródle operować. Dobrym zwyczajem jest jednak oddzielić model od bezpośredniego dostępu do danych.

V - widok. Miejsce, w którym wyświetlane są dane. I nic więcej.

C - kontroler. Odpowiada za przekazanie danych do widoku (nazywane inaczej wskazaniem z jakiego modelu skorzystać).

Obok "wielkiej trójcy" jest jeszcze takie coś jak dispatcher, po naszemu dyspozytor, czyli obiekt odpowiedzialny za odpowiednie rozprowadzenie ruchu między kontrolerami oraz za poprawne przekazanie danych, które zostały wysłane przez użytkownika.



* - nie chodzi tylko o pieniądze. Do kosztu można doliczyć czas, utrzymanie, zasoby serwera, itp.

Zanim zaczniesz/zaczniecie na mnie wieszać psy, za głoszenie herezji, określmy, czy rozmawiamy na poziomie akademickim, czy praktycznym. I w jakim kontekście? PHP, inny język, czy ogólnie.
darko
To zacznijmy od tego, że nie ma jednej, a nawet jednolitej implementacji/definicji wzorca mvc, są tylko nakreślone ogólne ramy i zasada działania. Z tego powodu nie powinniśmy rozmawiać, że coś odbiega od standardu, bo takowego po prostu nie ma, jest tylko mniej lub bardziej ogólna koncepcja, której wytyczne i wymagania są w taki czy inny sposób realizowane. Tymczasem rozwiązania frameworkowe mają - powiedzmy - odchyły od tych nakreślonych ram, z powodów, o których wspomniał ~batman - czyli upraszczając - skrócenie czasu wytwarzania kodu i "rozkmina" pod kątem RAD (rapid application development) a co za tym idzie - pieniądze. Ale powracając do MVC - jednym z głównych założeń jest podzielenie aplikacji na łatwo zarządzalne i jak najbardziej niezależne warstwy. Zastosowanie mvc ułatwia zarządzanie kodem, jego konserwację i... znowu pieniądze - im kod łatwiejszy w konserwacji tym tańszy w utrzymaniu. Często właśnie koszty wieloletniej konserwacji kodu kilkunastokrotnie przewyższają początkowy koszt jego wytworzenia. Ogólnie dyskusja ciekawa, niestety - temat rzeka.

// edit
ach... polecam lekturę tematu na forum
marcio
Cytat
Kontroler nie przekazuje żadnych danych z modelu do widoku. We wzorcu MVC widok jest sam zobligowany je pobierać z modelu, a przesyłanie ich przez kontroler to wymysł twórców Ruby On Rails i podobnych pionierskich frameworków, którzy źle spojrzeli na diagram i co później zostało powielone w milionach egzemplarzy jako obowiązujący dogmat.

Ja do pionerow nie naleze ale pokaz gdzie jest napisane ze "prawdziwe" MVC dziala tak a nie inaczej.
Jak juz napisal @batman,@darko ogolna definicja MVC to niezalezne bardziej lub mniej warstwy od siebie lepiej jak sa bardziej niezalezne a implementacja zalezy od programistow.
Twoje rozwiazanie jest lepsze bo wszystko robi sie prawie automatycznie ale zobacz ile potrzeba roboty.

Dyskusja podobna do tego jak implementowac plugin'y w aplikacjach mamy definicje plugin'a implementacja jest dowolna po co robic jakis super system plugin'ow z jednolitym API itp... jak sama aplikacja jest latwa i jako tako nie potrzeba tyle kombinowac by dzialala.
Zyx
Rozmawiamy na poziomie aplikacji WWW w ogóle, poziom częściowo akademicki, częściowo praktyczny.

Marcio, Batman -> pokazałem chyba jasno, GDZIE jest napisane, że interakcja między elementami MVC zachodzi tak, jak podaję. Jest jeden link, jest książka i są katalogi wzorców projektowych. Ponieważ widocznie ciężko jest poszukać i sprawdzić, podaję gotowe odnośniki:

http://java.sun.com/blueprints/patterns/MVC-detailed.html
http://martinfowler.com/eaaCatalog/modelViewController.html + szczegółowy opis w książce Patterns of Enterprise Application Architecture wydanej także w Polsce.

Pokażcie mi teraz Wy, gdzie w tych opisach jest jakiekolwiek słowo, że dane z modelu mają iść przez kontroler? Gdzie jest napisane, że widok TYLKO wyświetla dane? Ja widzę, że też je pobiera bezpośrednio z modelu.

Cytat
Jak juz napisal @batman,@darko ogolna definicja MVC to niezalezne bardziej lub mniej warstwy od siebie lepiej jak sa bardziej niezalezne a implementacja zalezy od programistow.


Ogólna definicja mówi nie tylko, że są trzy warstwy, bo gdyby to się do tego sprowadzało, to każdy po podstawowym kursie PHP tworzyłby aplikację MVC. Zabronisz mu nazwać skryptu kontrolerem, funkcji generującej kod HTML widokiem, a wywołań mysql_query() modelem? Ogólna definicja określa też podstawowe zależności, jakie powinny zachodzić między nimi, natomiast nie precyzuje sposobu ich wykonania. I tu dopiero wkracza implementacja, która zależy od programistów. Macie rację, wzorzec to ogólna definicja, ale definicja precyzuje nie tylko, CO powinno się znaleźć, ale JAK powinno ze sobą współpracować. Czy wzorzec obserwator byłby dalej obserwatorem, gdybyśmy wzięli dwie klasy i jedną nazwali obserwatorem, a drugą obserwowanym i nie zapewnili komunikacji, jaką ten wzorzec między nimi wymaga?

Cytat
Wszystko ładnie pięknie, ale to tylko teoria. A jak wiadomo od teorii do praktyki droga daleka. Implementacja MVC w "nowoczesnych" frameworkach, nie jest jakąś tam fanaberią kilku programistów, którzy zapragnęli być pionierami, tylko dobrze przemyślany wybór sztabu ludzi.


W porządku. Chcą tak robić, niech robią, tylko niech nie wmawiają ludziom, że to jest MVC.

Cytat
Przy projektowaniu jakiegoś rozwiązania należy wziąć pod uwagę przede wszystkim koszt*. Jeśli coś można zrobić taniej (co nie znaczy, że gorzej), to dlaczego tego z takiej możliwości nie skorzystać? Ślepe trzymanie się teoretycznych rozważań nie przyniesie nic dobrego. Spowoduje jedynie, że czas wykonania projektu znacząco się wydłuży, a niektóre funkcjonalności nie zostaną wdrożone, ponieważ "tak nie wolno".


Jakieś dowody, że gdyby zastosowali się do wskazań wzorca MVC, to byłoby inaczej? To, co napisałeś, jest suchym sloganem, który można podpiąć właściwie pod wszystko. Podaj mi choć jeden powód, na którym opierasz swoje przesłanki, że gdyby gotowy framework implementował MVC i udostępniał narzędzia RAD z nim współpracujące, to koszt i czas stworzenia aplikacji byłby większy w stosunku do tego, co się implementuje obecnie. Skoro nie ma żadnego przyzwoicie napisanego frameworka MVC, a jest mnóstwo frameworków pseudo-MVC, to jest raczej oczywiste, które rozwiązanie wypada lepiej w zestawieniu czas-koszty. Ale gdyby był?

Ja twierdzę, że prawdziwy MVC by wygrał i opieram to na doświadczeniu, gdyż tak się składa, że dane mi było pisać aplikację WWW zarówno jedną, jak i drugą techniką.
- Framework może dostarczać gotowe standardowe widoki, np. do CRUD, od razu implementujące stronicowanie, sortowanie itd. Narzędzia RAD mogą od razu generować modele, które z nimi współpracują, dzięki dobrze zdefiniowanym interfejsom.
- Jeśli to samo będziemy generowali w pseudo-MVC przy pomocy narzędzia RAD, gdyby standardowa definicja nam nie pasowała, musimy stworzyć własne narzędzie RAD, a to, co już jest wygenerowane, musimy przepisać. Tutaj czegoś takiego nie ma.
- Pseudo-MVC razem z olaniem zasad interakcji między trzema literkami wyrzucił też zasady precyzujące, gdzie powinny pracować poszczególne podsystemy. Powoduje to, że nie bardzo wiadomo, gdzie co umieszczać i (mówię o rzeczach w stylu formularzy, ACL, itp. itd):
* Każdy programista pisze inaczej, a my werbując nowego człowieka musimy go wdrożyć "w nasz system".
* Trudne wejście do technologii. Zauważ, ile nowi programiści mają pytań. Gubią się w tym wzorcu, nie wiedzą, co gdzie umieszczać, mają wiele wątpliwości co do zasady jego działania tym bardziej, że się wmawia im, że to jest MVC, tymczasem działa to tak samo, jak ich wcześniejszy teoretycznie-nie-MVC-kowy kod z tą różnicą, że pobieranie danych z bazy się nazywa modelem, a wyświetlanie widokiem. Tu widać także, do czego prowadzi olanie definicji wzorca, bo tak się składa, że w opisie MVC wiele z tych kwestii jest jasno i klarownie wyjaśnionych.
* Zamiast sięgnięcia do wzorca, tworzy się jakieś prowizoryczne nakładki w stylu filtrów, helperów, pluginów, tyle że każdy framework robi to po swojemu, nazywa po swojemu, definiuje po swojemu.
- Narzędzia RAD mogą wygenerować Ci co najwyżej CRUD. Przechodzisz do front-endu, który najczęściej ma już dość zróżnicowaną strukturę i musisz klepać wszystko samodzielnie. Tutaj pseudo-MVC przestaje już być pomocny, bo elementy modelu (ORM) walają się po kontrolerach, widoki są powiązane z konkretną akcją i część ich logiki też leży w kontrolerze. Jeśli chcemy mieć możliwość ponownego wykorzystania kodu, musimy ją sobie napisać sami. To ma być tańsze, prostsze i szybsze?
- Gdy przestaniemy utożsamiać widok z systemem szablonów, a model z ORM-em, technologia stanie się bardziej elastyczna. W obecnych frameworkach wymiana np. standardowego ORM-a na Doctrine, albo standardowego systemu szablonów na OPT to koszmar wymagający obudowania niemal całego systemu MVC rozmaitymi nakładkami, które praktycznie uniemożliwiają korzystanie z narzędzi RAD. W dodatku nie możemy np. użyć biblioteki wirtualnego systemu plików w roli modelu, bo z punktu widzenia frameworka to nie jest model smile.gif.

I nawiasem mówiąc w Javie łączenie widoku bezpośrednio z modelem jest normą i jakoś nikt nie narzeka, że jest to droższe, mniej efektywne itd.

Dodam jeszcze moje doświadczenie. Zacząłem korzystać z Zend Frameworka w 2006 roku, później pisałem m.in. w Kohanie. Po trzech latach dalej miałem mnóstwo wątpliwości, czy poszczególne elementy umieszczam we właściwym miejscu. Każdy eksperyment kończył się tym, że coś mi ciągle nie pasowało, ciągle coś nie było tak, jak być powinno, a cały kod był albo obudowany jakimiś cudacznymi konstrukcjami obiektowymi mającymi zapewnić wielokrotne wykorzystanie kodu, albo - jeśli trzymałem się "zaleceń" frameworka, nie różnił się specjalnie zasadą działania od kodu, który pisałem przed erą frameworków. Ot, pobieram dane z bazy, przetwarzam i pakuję do szablonu. A najgorsze było to, że wszędzie walono pustymi sloganami "tańsze i szybsze tworzenie aplikacji", tylko chyba w jakimś innym wymiarze. Dla mnie jedyna różnica była taka, że pod maską był ZF, Kohana, Yii, Symfony czy coś innego, a poza obecnością RAD i paru gotowych rzeczy, jak ACL, ORM itd. wszystko pisało się dokładnie tak samo. Później jakoś tak się złożyło, że musiałem coś w Joomli zrobić i przyszło olśnienie. Gdy widok połączyłem od razu z modelem, przyszło olśnienie i w parę dni miałem rozwiązanie wszystkich problemów, jakie napotykałem przy pseudo-MVC.
batman
~Zyx
Musisz pamiętać, że PHP != Java i implementacja MVC w obu językach będzie się różnić. Chociażby wspomniany wzorzec obserwatora. PHP działa od załadowania skryptu, do załadowania skryptu. Wszystkie sztuczki polegające na zapisie stanu aplikacji w sesji, czy ciasteczkach są tak naprawdę okrętką na brak wymaganej funkcjonalności.
Napisałeś, że Joomla ma dobrze zaimplementowany MVC. I tylko to jest dobrze zrobione w tym CMS. Wystarczy sprawdzić opinie na temat reszty kodu. O tak właśnie koszt mi chodzi.

Podałeś linka do dokumentacji Javy, w której opisane jest jak działać powinien MVC. Szkoda tylko, że opisano MVC w wersji Java. Ja wolę wersję dostarczoną przez Microsoft - http://www.asp.net/learn/mvc/tutorial-02-cs.aspx. W tej wersji kontroler służy do pobrania danych z modelu i przekazuje je (nie bezpośrednio) do widoku.

Możemy spierać się, czyja racja jest "mojsza", ale nie ma większego to sensu. Jeśli mamy dyskutować na temat MVC powinno zostać ustalone, że mówimy tylko o PHP i o możliwościach tego języka.
marcio
Cytat(batman @ 6.02.2010, 08:44:54 ) *
~Zyx
Musisz pamiętać, że PHP != Java i implementacja MVC w obu językach będzie się różnić. Chociażby wspomniany wzorzec obserwatora. PHP działa od załadowania skryptu, do załadowania skryptu. Wszystkie sztuczki polegające na zapisie stanu aplikacji w sesji, czy ciasteczkach są tak naprawdę okrętką na brak wymaganej funkcjonalności.
Napisałeś, że Joomla ma dobrze zaimplementowany MVC. I tylko to jest dobrze zrobione w tym CMS. Wystarczy sprawdzić opinie na temat reszty kodu. O tak właśnie koszt mi chodzi.

Podałeś linka do dokumentacji Javy, w której opisane jest jak działać powinien MVC. Szkoda tylko, że opisano MVC w wersji Java. Ja wolę wersję dostarczoną przez Microsoft - http://www.asp.net/learn/mvc/tutorial-02-cs.aspx. W tej wersji kontroler służy do pobrania danych z modelu i przekazuje je (nie bezpośrednio) do widoku.

Możemy spierać się, czyja racja jest "mojsza", ale nie ma większego to sensu. Jeśli mamy dyskutować na temat MVC powinno zostać ustalone, że mówimy tylko o PHP i o możliwościach tego języka.

To samo chcialem napisac tak samo z tego co widzialem w ASP.NET definicja MVC jest taka sama implementacja juz nie.
Ogolnie definicja jest taka sama dla kazdego jezyka gorzej z implementacja.
http://pl.wikipedia.org/wiki/MVC nie wiem czy wiki klamie,opisuje pseudo MVC,lub ja czegos nie rozumiem ale wiem jedno jest jasno napisane:
Cytat
Kontroler jest odpowiedzialny za odczyt danych z bazy danych (utworzenie modelu) i przekazanie ich do warstwy widoku (interfejsu użytkownika)

Wiec jak widac chyba w PHP przyjela sie taka a nie inna implementacja MVC.
A potem jak ktos chce ja sobie zmodyfikowac nie ma problemu nie dawno ktos tam wymyslil HMVC chyba nawet w KOHANA 3 zostalo zaimplementowane, nie wiem czym sie rozni bo nie czytalem ale jest ta nastepny odram MVC.

MNie jak narazie MVC pasuje tak jak je stosuje fakt faktem ze nic wielkiego na moim fw jeszcze nie napisalem jak narazie pisze ogolny system na ktorym bedzie mozna postawic praktycznie wszystko blog,cms,sklep i bog wie co jeszcze.
Fajnie by bylo jakbys nie rzucal linkami do Javy tylko podal jakis bardzo prosty kontroler,model i widok zgodny z twoja idea wtedy moze zrozumie o co ci chodzi choc sie domyslam.
POzdro.
Crozin
Ideę tego wzorca bardzo szybko i fajnie opisuje obrazek z wiki:
Cytat
http://upload.wikimedia.org/wikipedia/comm...llerDiagram.svg
Model-View-Controller concept. Note: The solid line represents a direct association, the dashed an indirect association via an observer (for example).
(niestety nie można wstawić bezpośrednio obrazu SVG)

W przypadku PHP ze względu na środowisko w jakim najczęściej ta technologia pracuje - czyli w obrębie protokołu HTTP komunikacja pomiędzy widokiem, a kontrolerem jest mocno ułomna ze względu na sam sposób działania tego protokołu. Cała reszta może być już poprawnie (w sensie bezproblemowo) zaimplementowana. Zauważcie, że kontroler jedynie "wywołuje" model, nie oczekuje od niego żadnych odpowiedzi, rezultatów.

Nie przepadam za odsyłaniem do wiki, ale po prostu jest to tam dobrze opisany ten wzorzec: http://en.wikipedia.org/wiki/Model–v...roller#Overview
Ponownie - to widok odpytuje model. Kontroler nic mu nie przekazuje, gdyż nie leży to w jego zakresie obowiązków.

@Zyx: chciałbym tylko zwrócić uwagę na to, że w Symfony sytuacja z modelem się nieco poprawiła ostatnim czasy. ORM (Doctrine) nie jest już tak silnie utożsamiany z modelem i poprawnie korzystając z niego możemy mieć porządnie zaimplementowany "pseudo-MVC", ale jak ktoś w kontrolerze robi coś w stylu (przykład akurat dot. Propela):
Kod
$c = new Criteria();
$c->...;
$c->...;
$c->...;
...Peer::doSelect($c);
I się dziwi, że nie ma burdel w aplikacji... to już jego wina.
dr4ko
Pierwotnie MVC został określony tak jak przedstawia go Zyx ale od tamtego czasu pojawiło się jego wiele wariantów które są stosowane przez całkiem poważnych programistów w całkiem poważnych aplikacjach. Tak naprawdę na dzień dzisiejszy MVC jest po prostu koncepcją podziału kodu aplikacji na warstwy a nie sztywnym schematem przepływu danych. Najczęściej stosowany na dzień dzisiejszy, w aplikacjach webowych, flow to właśnie widok->kontroler->model->kontroler->widok. Czytałem sporo publikacji na ten MVC, zapoznałem się z kilkoma wariantami, kilka z nich wypróbowałem w praktyce i uważam że najrozsądniejszym z nich jest mówiący o tym, że widok i kontroler powinny być nieświadome logiki zawartej w modelu, kontroler powinien zawierać logikę użytkową a model logikę biznesową, gdzie model otrzymuje i zwraca jedynie suche dane nie przejmując się istnieniem warstwy prezentacji. Mamy dzięki temu elegancką separację poszczególnych warstw i żadna nie jest ściśle powiązana z inną. Przykładem przewagi tego rozwiązania nad tym promowanym przez Zyxa jest możliwość działania aplikacji jako API przez przekierowanie danych w kontrolerze na wyjście zamiast do widoku. W tym innym wypadku musielibyśmy grzebać zarówno w kontrolerze jak i w modelu no i model musiałby mieć świadomość istnienia takiego a nie innego API co mocno ograniczyłoby przenośność kodu.

A o tym, że ORM!=model trąbiłem dawno temu w innym temacie winksmiley.jpg
thek
Ja w swoich pracach najczęściej korzystam z modelu wspomnianego przez dr4ko, gdyż jest moim zdaniem w chwili obecnej najbardziej adekwatny do sposobu działania aplikacji webowych, gdyż zgodna z przepływem informacji. User coś robi w widoku i te działania muszą być przechwycone, rozpoznane, a w tym celu powstał kontroler i to on musi zareagować odpowiednimi danymi wyciągniętymi z modelu. Te idelanie, gdyby mozna przesłać z modelu wprost do widoku. Tyle, że to wiązalo by się ze stworzeniem tak modelu, iżw odpowiedzi do widoku szedł by świetnie sparsowany i dostosowany do jego struktury pakiet danych lub widok zmieniał się dostosowując do formy odpowiedzi modelu. A to nie jest w zasadzie możliwe bez wpływu kontrolera. Najlepsze byłoby pełne uniezaleznienie warstw, gdzie każda mogła się odnosić do pozostałych bez konieczności pośrednictwa trzeciej czyli coś w stylu znaczka recycligu ale dwukierunkowego. Tylko czy jest realne do stworzenia takie coś, gdzie choćby model sam sobie wywołuje widok zależnie od danych?
cojack
Cytat(Kikert @ 5.02.2010, 15:07:36 ) *
Czyli bootstrap inicjuje kontroler, kontroler moduły, a na końcu widok, który korzysta np. z echo?


Ciebie można inicjować nie pytaj na co. INICJALIZOWAĆ!

@Zyx nie zgadzam się z Twoją wizją MVC.
Crozin
Cytat
@Zyx nie zgadzam się z Twoją wizją MVC.
Nie lubię takich trochę personalnych docinków, ale... nie ma to jak uargumentowana opinia. Poza tym to nie jest wizja Zyxa, tylko założenia tego wzorca (który nie był tworzony z myślą o "środowisku webowym", w którym to ten wzorzec najczęściej jest skopany).
marcio
Cytat
Nie lubię takich trochę personalnych docinków, ale... nie ma to jak uargumentowana opinia. Poza tym to nie jest wizja Zyxa, tylko założenia tego wzorca (który nie był tworzony z myślą o "środowisku webowym", w którym to ten wzorzec najczęściej jest skopany).

A gdzie tak jest napisane ze jest dobrze jak to on mowi na wiki na temat MVC pisza inaczej chyba ze mam problemy z czytaniem.
-=Peter=-
Cytat(marcio @ 13.02.2010, 15:25:12 ) *
A gdzie tak jest napisane ze jest dobrze jak to on mowi na wiki na temat MVC pisza inaczej chyba ze mam problemy z czytaniem.

Chyba masz problemy z czytaniem: http://en.wikipedia.org/wiki/MVC_Pattern#Overview
A konkretniej zdanie "A view queries the model in order to generate an appropriate user interface".

Osobną kwestią jest to, że wikipedia to nie zbyt wiarygodne źródło, zwłaszcza jeśli chodzi o takie informacje.

Prosty przykład w MVC jaki serwuje ZF, symfony i inne frameworki:
Chcemy pobrać stronicowaną listę elementów modelu, w kontrolerze (lub też w modelu) tworzymy obiekt paginatora, mówimy mu aby pobrał takie i takie elementy. Kontroler przekazuje paginator do widoku, który wyświetla to co w nim jest.

Konsekwencje: kontroler miesza się w warstwę prezentacji, bo to widok na podstawie modelu powinien decydować o tym czy dane są stronicowane i co ile. Chcemy zmienić liczbę wyświetlanych elementów lub wyłączyć stronicowanie, paradoksalnie musimy edytować kontroler - widok i kontroler wcale nie są niezależne.

W implementacji podanej przez @Zyxa to inaczej wygląda, w widoku (na podstawie danych zawartych w modelu) zachodzi decyzja czy dana lista ma być stronicowana, czy też nie. Kontroler jedynie mówi: ten i ten widok ma wyświetlić ten i ten model, nie mówi jak ma go wyświetlić, czy to ma być paginowalna lista, czy też nie. W tej implementacji MVC widok ma więcej zadań i w przeciwieństwie do znanych frameworków dla php potrzebnych będzie wiele klas widoku do różnych zadań.

Bezpośrednie powiązanie między widokiem, a modelem jest widoczne zwłaszcza w aplikacjach desktopowych, przykładowo Java i implementacja swingowej tabeli. Klasa JTable - widok, jest też jakaś klasa odpowiedzialna za model tabeli (nie pamiętam nazwy, pewnie JTableModel tongue.gif). Model przekazuje się bezpośrednio do konstruktora JTable, to widok bezpośrednio pobiera sobie dane z modelu, model może poinformować widok o tym, że zaszła w nim jakaś zmiana, a widok odświeży się (wzorzec obserwatora - pisał o tym @Zyx) - w aplikacjach www taki feature nie jest potrzebny gdyż http jest protokołem synchronicznym. Aplikacje dektopowe, a aplikacje internetowe to całkowicie dwie różne rzeczy, w aplikacjach www (mówię tutaj o frameworkach php) utarło się że to kontroler jest bliżej modelu niż widok, który służy tylko do prezentacji danych. Ma to swoje plusy oraz minusy.
Cysiaczek
@Zyx - Co do pobierania danych przez widok: http://www.apostrophenow.com
Szczególnie polecam manual dla developerów.

Pozdrawiam
marcio
Jak dla mnie to kontroler powinien zawierac cala logike kodu a widok tylko czesc prezentacyjna.
Cytat
Kontroler jedynie mówi: ten i ten widok ma wyświetlić ten i ten model, nie mówi jak ma go wyświetlić, czy to ma być paginowalna lista, czy też nie. W tej implementacji MVC widok ma więcej zadań i w przeciwieństwie do znanych frameworków dla php potrzebnych będzie wiele klas widoku do różnych zadań.

No wlasnie ja tak mam mam glowny widoku komponentu news a w nim miejsce dla paginacji jesli paginacja jest to tylko podpinam pod dana zmienna z szablonu widok paginacji i po wtokach nie musze ingerowac w kod modelu.
WiruSSS
Witam

Przepraszam, że odświeżam wątek, ale to chyba jedyny w języku polskim, gdzie jest dość głęboko poruszony ten temat.

Mam straszny mętlik, przez te wszystkie niejasności naprawdę zastanawiam się, czy nie zaniechać próby zastosowania.

Ogólnie chciałem zacząć programować, nie wiem czy z wykorzystaniem poprawnego modelu MVC czy nie, ale chyba w sposób podobny jak większość osób pojmuje MVC czy pseudo-MVC.

Więc:

Mam sobie plik index.php (z tego co wyczytałem powinienem nazywać go bootsraper czy jakoś tak). Daruję sobie jednak te wszystkie ładnie brzmiące pojęcia, niezrozumiałe dla 90% ludzi chcących cokolwiek z tego wszystkiego zrozumieć, więc wybaczcie biggrin.gif. Wracając do tego jak ja chciałbym tworzyć swoje aplikacje. Plik index.php, który w moim przypadku jest plikiem, gdzie są same includy.

Teraz chcąc być zgodny z MVC czy pseudo-MVC, tylko bardziej po swojemu tongue.gif, tworzę sobie 3 foldery _views, _controllers, _models.
Jak już wcześniej pisałem zdaję sobie sprawę, że samo MVC jest różnie interpretowane ale jakąś koncepcję muszę przyjąć więc przyjąłem taką:

_views - zawiera czyste pliczki html z wstawionymi danymi z modeli
_models - zawiera klasy z samymi zapytaniami do bazy czy odwolaniami do plików textowych, obrazkowych czy jeszcze innych, gdzie znajduja się jakiekolwiek dane
_controllers - zawiera klasy sterujące danymi i wysyłające je do odpowiednich widoków.

Bardzo chciałbym trzymać się przyjętej przeze mnie ideologii, jednak już w zasadzie na początku napotkałem na dość prozaiczne problemy.

Weźmy sobie ot taki prosty przykład jak menu, ktore widok powinien pokazać w taki sposób:

  1. <nav>
  2. <ul>
  3. <li><a href="link.html">link</a></li>
  4. <li><a href="link2.html">link2</a></li>
  5. <li><a href="link3.html">link3</a></li>
  6. <li><a href="link4.html">link4</a></li>
  7. </ul>
  8. </nav>


i teraz co zrobić, żeby pętelka wyświetliła mi te wszystkie
  1. <li></li>
...widzę 3 wyjścia i nie wiem które powinienem zastosować, każde wg mnie albo odbiega od przyjętego przeze mnie wzorca, albo komplikuje niepotrzebnie i rozdrabnia widoki:

przypadek 1: wewalam część kontrolera do widoku (dokładnie kod pętli) jednak cały kod html dzięki temu jest w widoku
przypadek 2: pętelka zostaje w widoku, jednak część kodu html
  1. <li><a href=""></a></li>
musi się znaleźć w kontrolerze.
przypadek 3: tworzę osobny, malutki widok
  1. <li><a href=""></a></li>
i teraz kontroler przy każdym kroku pętli korzysta z tego widoku, po czym na koniec całość wysyła do widoku menu.

Wg mnie żadne z tych rozwiązań nie jest poprawne i ciekawi mnie czy jest jakieś inne wyjście, które pozostanie zgodne z przyjętym przeze mnie wzorcem.

Jest jeszcze 4 przyadek gdzie ten kawałek html jest w modelu ale to też wydaje mi się bez sensu.

Bardzo proszę napraowadźcie mnie jak prawidłowo powinno się to zrobić, po kilku dniach próby zrozumienia o co w tym wszystkim chodzi, coraz bardziej utwierdzam się w przekonaniu, że albo nie nadaję się na webmastera i nie powinienem się wogóle nim określać, albo po prostu coś tutaj nie do końca jest przemyślane, lub wogólę nie pojmuję idei rozdzielenia poszczególnych warstw.

PS. Przepraszam, za tak prozaiczny przykład jednak myślę, że zbyt dużo czytamy w artykułach "ciężkich" tekstów z trudnymi przykładami i dlatego też wiele osób rezygnuje z prób dostosowania się do jakichkolwiek ogólnie przyjętych standardów. Bardzo bym chciał, żeby pojawiało się więcej bardzo prostych przykładów opisanych prostym językiem, bez zbednych niezrozumiałych terminów. Jakby ktoś był tak miły i spróbował przedstawić swoją interpretację MVC, jednak na konkretnym bardzo prostym przykładzie, choćby wyswietlenia prostego menu to już wogóle było by bosko smile.gif

dziękuję za uwagę i przepraszam jeśli moja wypowiedź nie jest na poziomie tego forum.
viking
PHP jest stosowane w widoku do prostego wyświetlania danych. Czyli pętla będzie prawidłowa. Ale lepiej by było gdybyś zastosował jakiś system szablonów np http://phptal.org gdzie ten kod miałby postać:
  1. <ul>
  2. <li tal:repeat="x y"><a tal:content="x.id"/></li>
  3. </ul>


Załóżmy. Czytelne, w postaci XMLowej i jeszcze z parsowaniem poprawności.
thek
Najprostsze rozwiązanie? Kontroler przekazuje do widoku tablicę (lub jakąkolwiek formę kolekcji). Elementy tej tablicy (kolekcji) też są tablicami (lub obiektami) i zawierają adres oraz anchor linku. Widok zawiera pętlę wyświetlającą:
Przykładowo:
W kontrolerze masz obiekt widoku, który ma składową odpowiedzialną za linki w menu:
  1. $view->links = array(
  2. array('link' => 'http://www.link1.com', 'anchor' => 'tekst1'),
  3. array('link' => 'http://www.link2.com', 'anchor' => 'tekst2'),
  4. array('link' => 'http://www.link3.com', 'anchor' => 'tekst3')
  5. );

W widoku masz do niej dostęp i możesz w pewnym jej fragmencie dać takie użycie:
  1. <ul>
  2. <?php
  3. foreach($links AS $link)
  4. {
  5. ?>
  6. <li><a href="<?php echo $link['link']; ?>"><?php echo $link['anchor']; ?></a></li>
  7. <?php
  8. }
  9. ?>
  10. </ul>
Tyle, że to nie jest już ściśle rzecz mówiąc MVC ale MVP. Nie ma tu bowiem tyle kontrolera, co prezenter, który pobiera dane z modelu i wrzuca do widoku.
WiruSSS
tak myślałem robić jednak mam odczucie że taki sposób jest jużniezgodny z samym MVC. Co do systemu szablonów może kiedyś się przkonam, jak narazie chciałbym korzystać z jak najmniejszej potrzebnej liczby rozszerzeń.
viking
Tylko pamiętaj że szablony są i tak kompilowane do czystego kodu PHP. Tylko dla jednej odsłony będzie więcej przetwarzania. A porównaj sobie kod obu przedstawionych rozwiązań i pomyśl że masz do przedstawienia coś bardziej zaawansowanego niż tylko ta jedna lista. Później jest taki bajzel że nie da się nad tym panować. Już nie mówiąc że te dane będziesz musiał jeszcze owinąć w htmlentities().
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.