Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ Pro _ Widok - renderowanie widoku

Napisany przez: Cysiaczek 12.09.2008, 15:38:06

Mam nadzieję, że trafię w gusta z takim tematem.
Dyskusja dotyczy szeroko rozumianego V w architekturze MVC, jego budowy i sposobów działania w różnych frameworkach i rozwiązaniach własnych.

Terminologia A
Proponuję przyjąć taką terminologię , aby nie było w dyskusji nieporozumień.

Widok to inaczej warstwa prezentacji wyników użytkownikowi. W budowie występują: format i renderer
Formatami są np. HTML, XML, plik tekstowy, obrazek
Rendererami dla formatu HTML są np. (gołe)PHP, Smarty, OPT


Dane widoku to wszelkie dane, przekazane do widoku przez kontroler lub dane, do których widok ma dostęp w inny sposób.
Proszę zatem nie pisać, "że widok pobiera dane z modelu", bo jeśli ma do niego dostęp, to model jest daną, którą widok potrafi zinterpretować.


Mile widziane diagramy UML lub inne, byle miały ręce i nogi smile.gif
Proszę nie zadawać pytań przedszkolnych!

P.S Jeśli ktoś ma jeszcze jakieś propozycje terminologii, proszę zgłosić mi, albo któremuś moderatorowi - jeśli będa sensowne, zostaną dodane w tym poście.
Jeśli ktoś się nie zgadza z tą terminologią, niech zaproponuje inną i zaznacza, której używa w dyskusji smile.gif Następna nazwa to 'B', potem 'C' itd

Pozdrawiam.

Napisany przez: orglee 12.09.2008, 17:23:25

Dobra to ja doleję oliwy do ognia i zacznę.
Format HTML versus XML. Jestem za pierwszym. Standard sprawdzony zaimplementowany w wielu projektach jak Wordpress.
Moim skromnym zdaniem główną jego przewagą nad formatem XML jest możliwość szczegółowej definicji sposobu wyświetlania w kodzie HTML.
Renderer taki jak Smarty parsuje 'pseudo-kod' który pozwala na zmianę formatowania poszczególnych elementów.
Tak niestety nie jest przy Rendererach XML. Załóżmy że FronController modułu wywołuje Controller akcji ( np. edytuj wpis w blogu )
Po czym dane są umieszczane, a nie przekazywane, bezpośrednio w widoku który jest plikiem XML. Zachodzi tutaj potrzeba utworzenia dodatkowej klasy która odpowiadałaby za manipulację widokiem lub rozszerzenie funkcji kontrolera akcji co mogłoby prowadzić do LavaFlow.
Jest to wielkim utrudnieniem jeśli praca jest podzielona między programistę i webmastera który ma za zadanie sformatować tylko sposób wyświetlania danych i wystarczyłaby mu odrobiona znajomości pseudokodu np. pakietu Smarty.

edit>
Jest to moim zdaniem o tyle bezsensu co przerzucanie się z dnia na dzień co chwile z różnych języków programowania.
Sprawa jest tutaj o tyle gorsza że PHP i HTML / XHTML mają ze sobą tylko tyle wspólnego że pierwszy używa dwóch pozostałych do prezentacji danych.
Więc jest to swojego rodzaju wybijanie się z rytmu.

edit>>
No co jest. Na prawdę liczyłem że ktoś mnie opieprzy i uświadomi że się baaaardzo mylę...

Napisany przez: LBO 13.09.2008, 21:16:47

Mnie osobiście denerwuje, że w MVC rozpowszechnionym przez ROR brakuje rzeczywistego podziału pomiędzy Widokiem, a Kontrolerem (lub akcją – umownie będę stosował termin kontroler).

Symfony:

  1. <?php
  2. // Proszę nie traktować poniższego przykładu dosłownie, wiem, że można
  3. // to po części zautomatyzować, ale chcę pokazać, że nie da się całkowicie uniknąć.
  4. class PostActions extends sfActions
  5. {
  6.  public function executeRead()
  7.  {
  8.   // pobieramy dane z modelu
  9.  
  10.  if ($this->getRequestParameter("type") == "pdf") {
  11.    // Generujemy post jako PDF
  12.    $this->getResponse()->setContentType('application/pdf');
  13.    // reszta kodu wykorzystująca np. Zend_Pdf
  14.  elseif ($this->getRequestParameter("type") == "mp3" ) {
  15.    // Generujemy post jako dźwięk – czyta Michał Żebrowski 
  16.    $this->getResponse()->setContentType('audio/mpeg3');
  17.    // reszta kodu wykorzystująca… cokolwiek co będzie dostępne pewnie za 50 lat
  18.  } else {
  19.     // to zapewne jest domyślne, ale zostawiam dla przejrzystości
  20.     $this->getResponse()->setContentType('text/xml');
  21.     // reszta kodu…
  22.  }
  23. }
  24. ?>


Podobnie ma się z innymi frameworkami tj. Cake, Zend, czy Kohana. Widok istnieje w nich bardziej jako abstrakcyjny byt. Fakt można to obejść – ZF proponuje zaimplementowanie logiki widoku w szablonach. Ale przecież szablon nie musi być PHPowy, może to być phpTAL, Smarty czy cokolwiek innego, pełniąc rolę tylko prezentacyjną (np. żadnego ustawiania nagłówków).
Co za tym idzie – w wymienionych przeze mnie frameworkach - nie ma miejsca na odseparowaną logikę widoku. Wszystko jest wszyte w kontroler – co mija się z jego celem jako pośrednika pomiędzy Modelem, a Widokiem.


@orglee - nie do końca rozumiem co napisałeś.
Chodzi Tobie o szablony, które są parsowane przez renderery, tak?

Napisany przez: orglee 13.09.2008, 22:29:43

No właśnie otóż to. Dla mnie widok jest to plik szablonu napisany w html czy xml czy czymkolwiek innym i przepuszczony przez renderer (np. smarty). Pisanie klasy widoku robiącej to co można zrobić za pomocą dosłownie odrobiny pseudokodu jest bez sensu. Nie wspominając że w dużej części frameworków, widok musi dziedziczyć po jakiejś super-duper specjalnej klasie w które jest 10 linijek kodu na krzyż i właściwie służy ona jedynie za kontener.

W moim poprzednim tekście chciałem dokonać porównania rendererów operujących na HTML i XML.
Może trochę nieprecyzyjnie się wyraziłem bo smarty można zastosować w obu przypadkach. Jednak do plików XML wydaje mi się że częściej są używane narzędzia bibliotek DOM jak również renderery korzystające z tych bibliotek. To samo w sobie narzuca konieczność tworzenia klas dla każdego widoku, nie robiących nic za wyjątkiem wklejania danych w odpowiednie miejsca.
Zapewne dalej jest to niewystarczające... ale cóż poradzić... analfabeta ze mnie.

Postaram się to trochę obrazowo wyjaśnić.
Smarty: FrontController.php, ControllerDisplay.php, ControllerEdit.php - model pomijam - display.html, edit.html
FW -> FC(akcja?) -> CD / CE -> dis / ed - Prosto i zrozumiale bez względu na to czy FC wywoła dis / ed czy zrobi to CD lub CE

DOMDocument(lub inne korzystające z niego): Smarty: FrontController.php, ControllerDisplay.php, ControllerEdit.php - model pomijam - display.view.php + display.xml, edit.view.php + edit.xml - Tutaj na pierwszy rzut oka widać że doszły pliki które mają manipulować widokiem. Już nie wystarczy jak przy smartach użyć assign i fetch tylko trzeba wiedzieć co gdzie wrzucić i właśnie umieszczenie danych z modelu następuje poprzez kod PHP w plikach *.view.php, co jest zwyczajnie niewygodne i niepotrzebnie komplikuje cały proces pisania widoku. Nie wspominając o ewentualnych modyfikacjach tego kodu.

edit>
Bardzo możliwe że mylę pojęcia w jakiś sposób.

Napisany przez: LBO 13.09.2008, 23:17:06

Cytat(orglee @ 13.09.2008, 23:29:43 ) *
No właśnie otóż to. Dla mnie widok jest to plik szablonu napisany w html czy xml czy czymkolwiek innym i przepuszczony przez renderer (np. smarty). Pisanie klasy widoku robiącej to co można zrobić za pomocą dosłownie odrobiny pseudokodu jest bez sensu. Nie wspominając że w dużej części frameworków, widok musi dziedziczyć po jakiejś super-duper specjalnej klasie w które jest 10 linijek kodu na krzyż i właściwie służy ona jedynie za kontener.


Nie zapominaj, że Smarty nie zrobi wszystkiego. PDF Tobie nie wygeneruje - bez czystego PHP się nie obejdzie.
Ale to część dyskusji, którą chciałem ja podjąć. Bardziej to związane z architekturą frameworków niż samymi rendererami. Jak będziesz miał ochotę zapraszam do dyskusji.

Cytat(orglee @ 13.09.2008, 23:29:43 ) *
W moim poprzednim tekście chciałem dokonać porównania rendererów operujących na HTML i XML.


Jako XHTML rozumiesz zagnieżdżony PHP w XHTML, tak?

Cytat(orglee @ 13.09.2008, 23:29:43 ) *
Może trochę nieprecyzyjnie się wyraziłem bo smarty można zastosować w obu przypadkach. Jednak do plików XML wydaje mi się że częściej są używane narzędzia bibliotek DOM jak również renderery korzystające z tych bibliotek. To samo w sobie narzuca konieczność tworzenia klas dla każdego widoku, nie robiących nic za wyjątkiem wklejania danych w odpowiednie miejsca.
Zapewne dalej jest to niewystarczające... ale cóż poradzić... analfabeta ze mnie.

Postaram się to trochę obrazowo wyjaśnić.
Smarty: FrontController.php, ControllerDisplay.php, ControllerEdit.php - model pomijam - display.html, edit.html
FW -> FC(akcja?) -> CD / CE -> dis / ed - Prosto i zrozumiale bez względu na to czy FC wywoła dis / ed czy zrobi to CD lub CE

DOMDocument(lub inne korzystające z niego): Smarty: FrontController.php, ControllerDisplay.php, ControllerEdit.php - model pomijam - display.view.php + display.xml, edit.view.php + edit.xml - Tutaj na pierwszy rzut oka widać że doszły pliki które mają manipulować widokiem. Już nie wystarczy jak przy smartach użyć assign i fetch tylko trzeba wiedzieć co gdzie wrzucić i właśnie umieszczenie danych z modelu następuje poprzez kod PHP w plikach *.view.php, co jest zwyczajnie niewygodne i niepotrzebnie komplikuje cały proces pisania widoku. Nie wspominając o ewentualnych modyfikacjach tego kodu.

Bardzo możliwe że mylę pojęcia w jakiś sposób.


Zgubiłeś sens Widoku i renderów we frameworkach. Najczęściej to są nakładki na systemy szablonów. Rozchodzi się o integrację. Jak będzie zrobiona umiejętnie z perspektywy Kontrolera/Akcji nie zauważysz różnicy, czy używasz Smarty, czy OPT.

Napisany przez: Cysiaczek 13.09.2008, 23:31:24

@orglee - To, że dla użytkownika frameworka model działania ogranicza się do: akcja - szablona nie oznacza, że cała ta warstwa jest taka prosta. Owszem, tworzenie za każdym razem klasy akcjaSzablon extends megaView jest idiotyczne z użytkowego punktu widzenia. Sam widok to jest mała aplikacja. Zawiera kontroler, który przed przed zleceniem przeparsowania szablonu dokonuje wyboru formatu i jego renderera. Musi to sprawdzić w konfiguracji, zareagować na żądania użytkownika (takie np. jak pokazał ~LBO w swoim poście). Mógłbym w akcji umieścić kod

  1. <?php
  2. $this->view->setRenderer('smarty');
  3. ?>

a w drugiej akcji
  1. <?php
  2. $this->view->setRenderer('opt');
  3. ?>

i jedyne o co musiałbym zadbać, to odpowiedni plik szablonu z kodem czytelnym dla tych rendererów.
Ba!
  1. <?php
  2. $this->view->setFormat('pdf');
  3. $this->view->setRenderer('myCoolPDFCreator');
  4. ?>

I już kontroler widoku musi wiedzieć, że poleci plik PDF, a nie HTML i odpowiednio przygotować nagłówki odpowiedzi, plugin z rendererem, przekazać mu dane i na końcu go uruchomić. Tym się właśnie zajmuje widok jako warstwa. Dlatego nie można go nazwać szablonem.

@LBO - gdzieś jednak musi zostać podjęta decyzja o formacie odpowiedzi. Można się pobawić w inteligentne rozpoznawanie, czego najprostszym przykładem są rozszerzenia
http://domain.pl/news.hml
http://domain.pl/news.xml
http://domain.pl/news.pdf
http://domain.pl/news.img

Teraz kontroler widoku może sam ustalić co zwróci do przeglądarki. Wystarczy, że w konfiguracji ustalimy taką dyrektywę i już smile.gif (nie mówię tu o Symfony, tylko o hipotetycznym FW, w którym można ustalać takie rzeczy poprzez wpisy w konfiguracji i przełączniki). W tym momencie kontroler (akcja) nic nie musi robić. W SF też domyślnie jest zwracany widok sfView::SUCCESS dla akcji jeśli w jej ciele nie zdecydujesz inaczej. Tak jak wspomniałem - gdzieś ta kontrola musi być zawarta.

Pozdrawiam

Napisany przez: orglee 13.09.2008, 23:59:15

Cytat
Nie zapominaj, że Smarty nie zrobi wszystkiego. PDF Tobie nie wygeneruje - bez czystego PHP się nie obejdzie.
Ale to część dyskusji, którą chciałem ja podjąć. Bardziej to związane z architekturą frameworków niż samymi rendererami. Jak będziesz miał ochotę zapraszam do dyskusji.
Hmm owszem. To jest coś czego pod uwagę nie brałem. Przy moim podejściu gdybym miał wygenerować PDF,
umieściłbym cały proces jego generacji w kontrolerze co zdaje się było by błędem i burzyłoby schemat MVC.
Cytat
Jako XHTML rozumiesz zagnieżdżony PHP w XHTML, tak?
Przez XHTML rozumiem język służący do prezentowania wyników tak jak HTML i nawet Flash czy wspomniany przez ciebie PDF. Natomiast przez PHP zagnieżdżone w XHTML czy HTML rozumiem sposób pobierania danych z modelu. Swoją drogą moim zdaniem nie najlepszy, bo słabo czytelny.

Cytat(Cysiaczek @ 14.09.2008, 00:31:24 ) *
(...)
No dobrze, ale mnie chodzi o prostotę wykonania. Czy byłoby wielkim zgrzytem w architekturze MVC gdybym w podanym przez LBO przykładzie z PDF'em zamiast uruchamiać widok którym jest dla mnie plik (x)html z pseudo-kodem smartów uruchomił bibliotekę w której specjalnie bym zaprogramował cały proces pobierania danych z modelu i generowania PDF'a ?
Może tutaj powinienem na dobrą sprawę zadać jeszcze inne pytanie. Czy mój sposób widzenia MVC jako wzorca w którym nie jest potrzebna odrębna klasa zajmująca się widokiem jest poprawny.

Napisany przez: LBO 14.09.2008, 00:31:40

Cytat(Cysiaczek @ 14.09.2008, 00:31:24 ) *
@LBO - gdzieś jednak musi zostać podjęta decyzja o formacie odpowiedzi. Można się pobawić w inteligentne rozpoznawanie, czego najprostszym przykładem są rozszerzenia
[url="http://domain.pl/news.hml"]http://domain.pl/new... /ciach/


To się rozumie samo przez się smile.gif Korzystam z Agavi i chyba zrobię mała prywatę:

  1. <?php
  2.  
  3. class Post_BrowseSuccessView extends BlogaviBaseView
  4. {
  5.    // Wypluwamy HTML
  6.    public function executeHtml(AgaviRequestDataHolder $rd)
  7.    {
  8.        // Routing ustalił na podstawie urla, że akcja ma wypluć HTML
  9.        
  10.        $this->setupHtml($rd, 'master'); // ustawiamy layout
  11.        
  12.        // Kontroler już odwalił bródna robotę - pobranie danych z bazy poprzez model
  13.        // i wybranie (zwrócenie nazwy) odpowiedniego widoku np. Success, Error, Input - i przekazał
  14.        // listę artykułów do widoku (dostepną w tutaj z poziomu metody
  15.        // AgaviVi::getAttribute('list_of_articles').
  16.        
  17.        // Ustawiamy zmienną specyficzną dla HTML <title />
  18.        // Można też z modelu dociągnąć inne specyficzne/dodatkowe dla danego formatu dane.
  19.        $this->setAttribute('title', 'Lista artykułów.');
  20.        
  21.        // Następnie kotroler/dispatcher przechodzi do szablonu.
  22.        // Szablon może byc różny, gdyz w konfigu można zaznaczyć jaki
  23.        // renderer ma być użyty (jak i ustawić własny); Może to być czysty PHP,
  24.        // phpTAL, OPT etc.
  25.    }
  26.  
  27.    // Wypluwamy Json
  28.    public function executeJson(AgaviRequestDataHolder $rd)
  29.    {
  30.        // Routing ustalił na podstawie nagłówka (np. 'X-Requested-With' == 'XmlHttpRequest'), że akcja
  31.        // ma wypluć JSON - to o czym pisałeś Cysiaczku:)
  32.        
  33.        // Agavi pozwala skonfigurować nagłówki dla konkretnych formatów
  34.        // zwanych tutaj output_types. Mozna też ustawić ręcznie.
  35.        $this->container->getResponse()->setContentType('application/json');
  36.        
  37.        // Wynik jest zwracany bezpośrednio z pominięciem szablonu.
  38.        return json_encode($this->getAttribute('list_of_articles'));
  39.    }
  40.    
  41.    // Wypluwamy CSV
  42.    public function executeCSV(AgaviRequestDataHolder $rd)
  43.    {
  44.        $this->container->getResponse()->setContentType('text/csv');
  45.        
  46.        // Poniżej logika (logika widoku) budowania dokumentu CSV
  47.        $csv = http://www.php.net/fopen('p://temp', 'r+');
  48.        fputcsv($csv, $this->getAttribute('list_of_articles'));
  49.        http://www.php.net/rewind($csv);
  50.        return $csv; // Tutaj magia Agavi - sama wykryje, że zwracany jest handler pliku i go wypluje.
  51.    }
  52. }
  53.  
  54. ?>


Jak widzicie widok to zestaw klas obsługujących równolegle (ale oddzielnie) różne formaty wynikowe. Dzięki temu, zostawiamy akcji tylko to czym ma się zająć - pobraniem danych i przekazaniem do odpowiedniego widoku.
Sam widok Agavi, jest znacznie bardziej rozbudowany, gdyż na przykład layouty (w większości frameworków zwykłe szablony ze zdefiniowanych miejscem "wklejenia" wyniku aktualnej akcji) mogą składać się z kilku warstw, gdzie do każdej może być przypisany inny renderer (tak, można mieć jednocześnie Smarty i OPT biggrin.gif). Na dodatek można layouty modyfikować in runtime (programistycznie) dodając lub usuwając wybrane warstwy.

Napisany przez: Cysiaczek 14.09.2008, 00:32:29

Coś czuję, że zaraz znów rozbijemy się o rozumienie MVC smile.gif
Moim zdaniem jest poprawny, ale ubogi funkcjonalnie i trudny w rozbudowie. Jeśli wiążesz warstwę z konkretną implementacją, to sam potem sobie jesteś winien, jeśli tą warstwę przyjdzie Ci wymieniać, albo dodać inną - alternatywną (choćby celem przetestowania)
Jeśli chodzi o ten PDF, to w kontrolerze sobie to inicjujesz (tu obiekt sam już korzysta z modelu, na własną rękę), przekazujesz zainicjalizowany obiekt do obiektu transportującego dane dla widoku i tu masz np. dwa wyjścia.
1.
SzablonAkcji.php

  1. <?php
  2. $pdf->display();
  3. ?>


2. Zaimlementowanie w obiekcie PDF np. interfejsu, który jest rozumiany przez widok i który widok sobie sam uruchomi
  1. <?php
  2. interface Displayable
  3. {
  4.  public function display();
  5. }
  6. ?>

Sorry za to Displayable, bo nawet nie wiem, czy takie słowo istnieje tongue.gif
MVC to prosty wzorzec, ale jest bardzo abstrakcyjny i jego implementacje mogą posiadać po wiele różnych warstw. W aplikacjach koropracyjnych wyróżnia się w sumie 4 warstwy (Obiekty wzorce narzędzia str. 246.):
1. Warstwa widoku
2. Warstwa poleceń i kontroli
3. Warstwa logiki biznesowej
4. Warstwa danych

1+2=warstwa prezentacji (widok)

Więc nie trzymajmy się pojęcia MVC jako jedynego słusznego i nie ograniczajmy się do tych 3 warstw. Temat służy zaprezentowaniu różnych koncepcji smile.gif

Napisany przez: LBO 14.09.2008, 00:42:15

Cytat(orglee @ 14.09.2008, 00:59:15 ) *
Może tutaj powinienem na dobrą sprawę zadać jeszcze inne pytanie. Czy mój sposób widzenia MVC jako wzorca w którym nie jest potrzebna odrębna klasa zajmująca się widokiem jest poprawny.


Jest poprawny, ale bardzo ograniczony. Juz wystarczy, że w większości frameworków widok to w zasadzie obiekcik, który zwyczajnie potrafi obsłużyć przyjmowanie danych i przekazywanie do szablonu - bardzo biednie. W zasadzie to jest klasa-nakładka na system szablonów - wymusza pewien interfejs i tyle.

Napisany przez: orglee 14.09.2008, 01:00:09

Mam propozycję. Może zdefiniujmy czym powinno się zajmować to nasze wspaniałe V.
Z tego co napisaliście mogę założyć, że powinien on umieszczać dane w szablonie i wybierać renderer.

Ok. Jednak w moim przypadku w FW szablon sam importuje obiekty modelu. Zostaje tylko wybór renderera którego już w tym momencie zmienić nie mogę. Jeśli renderer miałby zostać użyty inny to można by było umieścić kod odpowiedzialny za jego wybór w kontrolerze akcji, co nie było by moim zdaniem naruszeniem zasad MVC. Nie sądzę żeby nawet dla tych dwóch potrzeb należałoby tworzyć odrębną klasę, a co dopiero dla jednej. Tak więc czy są jeszcze jakieś inne zadania które można przydzielić widokowi ?

Napisany przez: Cysiaczek 14.09.2008, 01:25:37

Ja od zawsze forsuję prosty podział widoku na:
1. Logikę widoku
2. Szablon widoku

Logika nie musi być rozbudowana, bo w małych FW może być prosta i ograniczać się jedynie do wywołania szablonu i przekazania mu danych
Szablon to to co wszyscy znają jako pliki .tpl, czy .php - konkretny wygląd dla danych.
Siłą rzeczy, przy taki podziale dyskusja skupia się na tym, co w tej logice widoku być powinno i gdzie powinna być umiejscowiona (bo może być właśnie w szablonie). Czym się powinna zajmować logika widoku? Moim zdaniem tym, co napisałem w drugim poście smile.gif

Napisany przez: Black-Berry 14.09.2008, 10:19:25

Cytat
No właśnie otóż to. Dla mnie widok jest to plik szablonu napisany w html czy xml czy czymkolwiek innym i przepuszczony przez renderer (np. smarty)
Ja również korzystam z systemu szablonów ale w formacie .phtml (html+php) i na razie sprawdza się to dobrze. Gdybym używał templatek renderowanych to chcąc np dodac datę do swojego szablonu musiałbym przekazać ją w argumancie lub mieć odpowiednie metody w renderze zamieniające znacznik {actual_date} na coś innego. Render musiałby też odpowiednio formatowac datę bo nie każdy lubi format xxxx-xx-xx. Przekazywanie w argumencie to też spora rozrzutność bo jeśli stawiam nowy serwis to duża część argumentów może być wogóle niewykorzystana.

Czasami templatka musi posiadać np. pager więc tworzy nowy obiekt klasy Pager. Czy to nie jest przypadkiem nadużycie bo wydaje mi się, że mój sposób narusza wszelkie modele powiązane z MVC. Z drugiej strony nie wyobrażam sobie korzystania ze Smarty. Tworzenie rendera tylko po to aby trzymać się kanonu jest dla mnie nie zrozumiałe. W aplikacjach internetowych priorytetem powinna być wydajność.

Mam nadzieję ze za bardzo nie odszedłem od tematu smile.gif

Napisany przez: LBO 14.09.2008, 10:26:15

Cytat(Black-Berry @ 14.09.2008, 11:19:25 ) *
Czasami templatka musi posiadać np. pager więc tworzy nowy obiekt klasy Pager. Czy to nie jest przypadkiem nadużycie bo wydaje mi się, że mój sposób narusza wszelkie modele powiązane z MVC.


A dlaczego? Póki ten pager nie ma nic wspólnego z logiką biznesową, wszystko jest w porządku - zrobiłeś sobie tylko helpera, który bez tony if'ów wypisuje to czego chcesz.

Napisany przez: dr_bonzo 14.09.2008, 19:55:51

Dane do widoku wybieram w kontrolerze, widok (zwykla tpl) tez moze je sobie pobrac.
Moj Pager jest zaprzeczeniem MVC, "tpl" pagera znajduje sie w dostepie do danych (DAO/ORM), konfigurowalne i latwe w uzyciu, chociaz wyraznie lamie podzial na logike biznesowa/dao i na widok.

Napisany przez: Sedziwoj 16.09.2008, 12:38:52

Mi też się wydaje że problemem jest raczej ustalenie jak to ma się dzielić, gdzie co wykonywać, a nie jak to zaimplementować.
bo mamy konkretną akcję, ona pobiera dane, obrabia, i tu nasuwa się pytanie co dalej, przekazuje do widoku, ale z tego co się mówi, to ta akcja powinna wybrać jaki.
I teraz te dane trafiają do widoku, czy to będzie Smarty/OPT/XML/PDF tworzony (jeśli jest, bo przy czystym html+php niema) odpowiednie obiekty i przekazywane dane oraz "szablon", i tu dla Smart to plik *.tpl, dla PDF to zunifikowany obiekt renderera, który będzie umiał wygenerować dokument wykorzystując obiekt stworzony w widoku. Potem widok uruchamia display na tym generujący i na tym kończy swoje działanie.

Tak to wygląda moim zdaniem, aby rozdzielić coś co generuje Smarty itd. od konkretnego przypadku *.tpl czy renderera dla PDF.
Sama akcja na podstawie jakiś danych powinna określić co będzie tym generatorem, a sam generator wie jaki typ danych zwraca.

Napisany przez: LBO 16.09.2008, 12:57:24

Cytat(Sedziwoj @ 16.09.2008, 13:38:52 ) *
/ciach/


Czyli tak jak pisałem - logika widoku powinna byc oddzielona od logiki kontrolera.
Ale jednak nie zgadzam się z wyborem rendera w akcji - to powinno byc transparentne dla niej. Świetny sposób, by dodawać różne formaty prezentacji do tej samej akcji, bez ruszania jej kodu.

Napisany przez: dr_bonzo 16.09.2008, 13:04:53

U mnie, w akcji, wybierany jest typ odpowiedzi.
Tworzy to obiekt odpowiedzi (Response), ktory dostaje dane z akcji i ma interfejs: pushContents() + pushHeaders(), dzieki czemu jestem w stanie wygenerowac dowolna odpowiedz dowolnego typu (wlasciwie to jest polaczony Response z obiektem Renderera)

  1. <?php
  2. $response->pushHeaders() ; // a w srod: header( ... ) etc.
  3. $response->pushContents(); //  w srodku echo "...." etc (albo mam return:P nie pamietam)
  4. ?>



edit:
@LBO: a wlasnie, bede wkrotce mial wybor renderra "rozszerzeniem pliku z URLa requestu" http://.../post/show/1.(xml|html|pdf) etc.
Tzn w kontrolerze mam dostep do $this->getResponseFormat() i sproboje to automatycznie podpiac do wyboru tego renderera.

Napisany przez: LBO 16.09.2008, 13:22:30

dr_bonzo: Rozumiem, że posiadasz jakis router do Tego, prawda? Czy to bedzie konfigurowalne, czy na stałe zaimplementujesz wyciaganie rozszerzenia z url'a?

Napisany przez: dr_bonzo 16.09.2008, 13:33:17

Oczywiscie mam router, wlasnie on sie zajmuje rozpoznaniem formatu (oprocz odczytania pozostalych parametrow z URLa)

Napisany przez: Sedziwoj 16.09.2008, 16:00:08

Od samego typu widoku nie jest zależne która akcja się wykona, więc to nie Router powinien decydować jaki będzie "typ" wynikowy. To już jest poziom kontrolera. Można oczywiście wykorzystać mainControler do tego, ale to jednak w nim powinien być wybierany widok.
Pytanie, jak z szablonami html wiadomo, mają określoną nazwę i lokalizacje i w tan sposób są dobierane, to jak sprawa przy PDF, gdzie musi istnieć klasa która umie wygenerować odpowiednie dane wynikowe? W sumie to sam widok powinien wiedzieć jaka jest domyślna konfiguracja, więc można dla PDF tworzyć unikatowe klasy renrerer'ów, które by potrafiły obsłużyć to co widok dostał.
(chyba muszę sobie przyswoić lepiej słownictwo, bo się nie dogadamy ;] )

A no i to sam widok określa jaki typ jest zwracany, bo on wie kim jest, nie ma żadnego ustawiania.

Ogólnie tym do czego dążę to aby mieć jakieś widoki (Smatry/OPT/XML/PDF/JSON) i do nich odpowiednie "renderer"y dla smarty .tpl, dla PDF odpowiednia klasa itd.
Dzięki temu, jakby ktoś chciał zmienić system szablonów wystarczy zaimplementować odpowiedni interfejs/abstrakcje widoku i dla miejsc wystąpienie potrzebne renderery. W czym renderery nie są jakoś zunifikowane, bo należą tylko do widoku.

EDIT: literówka

Napisany przez: LBO 16.09.2008, 20:51:29

Cytat(Sedziwoj @ 16.09.2008, 17:00:08 ) *
Od samego typu widoku nie jest zależne która akcja się wykona, więc to nie Router powinien decydować jaki będzie "typ" wynikowy. To już jest poziom kontrolera. Można oczywiście wykorzystać mainControler do tego, ale to jednak w nim powinien być wybierany widok.


Jak nie? Przecież router tłumaczy URLe, parametry z CLI, komendy głosowe (biggrin.gif) jaką akcje ma wykonać? Tym samym wydaje mi się, że od niego zależy jaki format wynikowy ma być. Dla CLI, czy SOAP to będzie jasne, ale dla web requestów już nie (HTML, (AJAX) JSON, (AJAX) XML).
Kontroler/Akcja ma byc niezależna od formatu wynikowego. Dlatego tak potepiam te stosy ifów sprawdzających rodzaj żądania i generujacych odpowiedni output w wewnątrz akcji.

[edit]Hmmm, tak myślę, że może nie tyle Router, co warstwa requestu.[/edit]

Zauważyłem właśnie, że strasznie dużo ludzi utożsamia widok z renderem.

  1. <?php
  2. // pseudo costam kontroler
  3. function executeListingAction($request_parameters) {
  4.    $model = new SomeListingModel();
  5.    $listing = $model->getAllByPage($request_parameters['page']);
  6.  
  7.    // i tutaj pies pogrzebany, bo patrząc na większość frameworków
  8.    // $this->view jest instancją jakiejś nakładki np MyFrameworkSmartyView,
  9.   // MyFrameworkOptView, albo MyPDFView, czyli w istocie renderera.
  10.    $this->view->set('listing', $listing);
  11.  
  12.   // i co potem?
  13.   if($this->request_type == 'pdf') {
  14.      $this->resonse->setContentType('application/pdf');
  15.      $this->view->setPDFTemplate('templates/listing.pdf'); // bo tutaj renderer obsluguje PDF, nie ma tego w podstawowym interfejsie klasy widoku. bleh!
  16.   } else if($this->request_type == 'ajax') {
  17.      $this->resonse->setContentType('application/json');
  18.   }
  19.   // gdzie tu jakikolwiek podzial kontrolera/akcji od widoku?
  20. }
  21. ?>


Cytat(Sedziwoj @ 16.09.2008, 17:00:08 ) *
Pytanie, jak z szablonami html wiadomo, mają określoną nazwę i lokalizacje i w tan sposób są dobierane, to jak sprawa przy PDF, gdzie musi istnieć klasa która umie wygenerować odpowiednie dane wynikowe? W sumie to sam widok powinien wiedzieć jaka jest domyślna konfiguracja, więc można dla PDF tworzyć unikatowe klasy renrerer'ów, które by potrafiły obsłużyć to co widok dostał.
(chyba muszę sobie przyswoić lepiej słownictwo, bo się nie dogadamy ;] )


Lepiej stworzyć widok(i) akcji, który bedzie potrafil obsluzyć kilka rodzajów formatów wyjściowych w tym np. modyfikować dane z kontrolera i dopiero je przekazywać do renderera. O tyle wygodniej, że nie trzeba robić renderera JSON, bo wystarczą fukcje natywne.

Cytat(Sedziwoj @ 16.09.2008, 17:00:08 ) *
A no i to sam widok określa jaki typ jest zwracany, bo on wie kim jest, nie ma żadnego ustawiania.

Ogólnie tym do czego dążę to aby mieć jakieś widoki (Smatry/OPT/XML/PDF/JSON) i do nich odpowiednie "renderer"y dla smarty .tpl, dla PDF odpowiednia klasa itd.
Dzięki temu, jakby ktoś chciał zmienić system szablonów wystarczy zaimplementować odpowiedni interfejs/abstrakcje widoku i dla miejsc wystąpienie potrzebne renderery. W czym renderery nie są jakoś zunifikowane, bo należą tylko do widoku.

EDIT: literówka


O i doszedłem do Tego, przeczytałem i też mi się podoba. Chociaż trochę sie skrzywiłem, na to, że dla każdego rendera na twardo będzie trzeba obsługę formatu wpisać (czyli ten skrypt PHP dla PDF i tpl dla Smartów). Nic nie przebije samego PHP gdzieś pomiędzy jeszcze - chociażby mozliwości jego użycia.

Napisany przez: orglee 17.09.2008, 08:57:51

Cytat(LBO @ 16.09.2008, 21:51:29 ) *
Jak nie? Przecież router tłumaczy URLe, parametry z CLI, komendy głosowe (biggrin.gif) jaką akcje ma wykonać? Tym samym wydaje mi się, że od niego zależy jaki format wynikowy ma być. Dla CLI, czy SOAP to będzie jasne, ale dla web requestów już nie (HTML, (AJAX) JSON, (AJAX) XML).
Kontroler/Akcja ma byc niezależna od formatu wynikowego. Dlatego tak potepiam te stosy ifów sprawdzających rodzaj żądania i generujacych odpowiedni output w wewnątrz akcji.
No dobra, ale co z sytuacją kiedy moduł reaguje inaczej na element który wymusza w routerze zmianę typu wynikowego. Owszem sytuacja niszowa i wątpię czy kiedykolwiek się z nią spotkam, ale wtedy istnieje konieczność zmiany generowania typu odpowiedzi w module. ( swoją drogą pomysł z rozpoznawaniem przez rozszerzenie jest bardzo fajny )
-- Dobra sam już sobie odpowiedziałem na mój bezsensowny zarzut do tej metody. Też jestem za tym żeby router ustawiał typ odpowiedzi.
Mam tylko jeszcze zastrzeżenie co do wykrywania typu odpowiedzi. Ile jest typów dokumentów ? Chyba tego nie wie najstarszy programista.
Co w związku z tym ? Ano tylko że obsłużyć kilka standardowych a resztę olać ustawiając domyślny ?

Teraz pytanie o wyniki widoku.
Klasa V powinna sama pakować dane do obiektu który ma je wyświetlać czy zwracać wynik do kontrolera akcji który się tym zajmie ?

CLI - Command Line Interface ? eee ?

Napisany przez: LBO 17.09.2008, 10:01:52

Cytat(orglee @ 17.09.2008, 09:57:51 ) *
Mam tylko jeszcze zastrzeżenie co do wykrywania typu odpowiedzi. Ile jest typów dokumentów ? Chyba tego nie wie najstarszy programista.

Co w związku z tym ? Ano tylko że obsłużyć kilka standardowych a resztę olać ustawiając domyślny ?


Jeżeli masz dobry router, elastyczny i genialny, nie musi to być po rozszerzeniu. Możesz ustawić, że /blog/post/read/my-title ustawiają format wynikowy na domyslny, /blog/post/read/my-title.html ustawiają format wynikowy na HTML, /blog/post/read/my-title.pdf na PDF, a na przykład /ajax/blog/post/read/my-title wymuszają JSON - ja tak robię smile.gif

Cytat(orglee @ 17.09.2008, 09:57:51 ) *
Teraz pytanie o wyniki widoku.
Klasa V powinna sama pakować dane do obiektu który ma je wyświetlać czy zwracać wynik do kontrolera akcji który się tym zajmie ?

CLI - Command Line Interface ? eee ?


Nie rozumiem. Mógłbyś wyjaśnić?

Pozdrawiam, Alan

Napisany przez: dr_bonzo 17.09.2008, 11:02:01

[ot] CLI = Command Line Interface

Napisany przez: orglee 17.09.2008, 13:46:35

Zależnie od architektury frameworka wynik produkowany przez moduł jest wysyłany bezpośrednio do przeglądarki, pakowany do obiektu wyświetlającego który wykonuje dodatkowe zadania ( np. pakuje gzip'em ) lub zwracany do klasy kontrolującej ładowanie modułu.

W moim FW wynik jest pakowany do klasy wyświetlającej 'Output'.
Stąd moje pytanie. W którym miejscu wynik wygenerowany przez moduł powinien być przekazywana do klasy Output w celu dalszej obróbki?


  1. <?php
  2. if(CLI == 'Command Line Interface') {
  3. http://www.php.net/echo 'W takim razie nie rozumiem do czego LBO odniosłeś CLI w swoim poście';
  4. }?>

Napisany przez: LBO 17.09.2008, 14:17:38

@orglee http://us3.php.net/features.commandline, odczytywanie argumentów mimo mimo, że natywnie proste, nie jest elastyczne.


Kod
php /usr/some_project/console.php post read 1 # kieruje na kontroler post, akcje read, id = 1

php /usr/some_project/console.php delete 100 comment  #kieruje na kontroler comment, akcje remove, id = 100

php /usr/some_project/console.php cleanup_session # kontroler default akcja cleanSession



To są ekstramalne przypadki, ale pokazują, że router się przydaje i tutaj.

Cytat(orglee @ 17.09.2008, 14:46:35 ) *
W moim FW wynik jest pakowany do klasy wyświetlającej 'Output'.
Stąd moje pytanie. W którym miejscu wynik wygenerowany przez moduł powinien być przekazywana do klasy Output w celu dalszej obróbki?


Ale co generuje moduł? Tylko zmienne? Czy już HTML/PDF?

Napisany przez: quality 2.03.2011, 08:47:36

Witam.
A czy ktos uzywal kiedys XSLT do renderowania widoku ? smile.gif
Znajomy ostatnio mi pokazal jak fajnie mozna tego uzyc. Generujemy plik XML z wszystkimi danymi, a nastepnie szablon w XSLT, ustawiamy naglowki na HTML i mamy pieknie wyrenderowana strone przez przegladarke, badz parser smile.gif

Napisany przez: Speedy 9.04.2011, 15:53:42

Cytat(quality @ 2.03.2011, 09:47:36 ) *
Witam.
A czy ktos uzywal kiedys XSLT do renderowania widoku ? smile.gif
Znajomy ostatnio mi pokazal jak fajnie mozna tego uzyc. Generujemy plik XML z wszystkimi danymi, a nastepnie szablon w XSLT, ustawiamy naglowki na HTML i mamy pieknie wyrenderowana strone przez przegladarke, badz parser smile.gif


Kiedyś się tym bawiłem w ramach eksperymentów, ale było to dawno temu. Nie wiem, czy ta technologia się zmieniła od tamtego czasu, bo do niczego konkretnego jej nie używałem.
Jedyne, co pamiętam, to fakt, że arkusze XSLT są przetwarzane po stronie klienta i jest za to odpowiedzialna przeglądarka. W związku z tym, w jednej przeglądarce wszystko wyświetlało się, jak należy, a w innej już nie. Moim zdaniem, używanie tego na co dzień może być dość ryzykowne, ponieważ nie masz pewności, czy wszystko zostanie przetworzone i wyświetlone, jak należy. Musiałbyś wcześniej porobić jakieś testy. Poza tym, jest to trochę inne zagadnienie, niż klasyczne renderowanie widoku, gdyż PHP robi wszystko po stronie serwera, natomiast tutaj cała akcja dzieje się po stornie klienta.

Napisany przez: everth 9.04.2011, 16:04:29

XSLT też może być przetwarzane po stronie serwera i wydaje mi się to nawet bardziej rozpowszechnione niż sposób o którym mówisz. Mniej problematyczny, robiłem tak przez pewien czas, jednak formuła Widok -> XML -> XSLT -> HTML jest jednak trochę przekombinowana jak dla mnie.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)