Some of posts from this blog has been moved to dywicki.pl. You will be automatically redirected to new blog if you would submit comment.
New posts are published on dywicki.pl, this blog contains old content and it is not continued.

Niektóre posty z tego bloga zostały przeniesione do dywicki.pl. Zostaniesz automatycznie przekierowany jeśli bedzięsz chciał dodać komentarz.
Nowe posty sa publikowane na dywicki.pl, ten blog zawiera stare treści i nie jest kontynuowany.

Agavi, Output types

Filed under Agavi,Framework,MVC,PHP by

Jedną z nowości jaką niesie Agavi w wersji > 0.10 jest mechanizm output types. Jest to bardzo proste rozwiązanie, które umożliwia uniknięcie gimnastyki z tworzeniem widoków w różnych technologiach, z którymi wiąże się różna logika. Banalny przykład. Te same dane prezentujemy w postaci HTML jak i PDF a do tego możemy je pobierać przez XmlHttpRequest. Dane są praktycznie identyczne, różny jest format wynikowy i proces jego tworzenia. Dla zwykłej strony wskazujemy szablon, dorzucamy dane i koniec, dla XmlHttp zwracamy JSONa. Stworzenie outputu w formacie PDF nie będzie tak proste jak pozostałych, ponieważ konieczne będzie stworzenie układu strony, dorzucenie fontów etc. Ogólnie w żaden sposób nie da się połączyć tych formatów w jednym widoku bez sporej ilości warunków i "protez". By uniknąć zakopania się w tym wszystkim zwykle tworzy się dodatkową akcję, która w sporej części pokrywała się z pierwotną a różni się tylko widokiem i szablonami. Począwszy od Agavi 0.11 problem przestaje istnieć.

W pliku konfiguracyjnym output_types.xml określamy renderer dla danej technologii, dodajemy obiekty przedefiniowane (parameters name="assigns") i następnie konfigurujemy mapowania adresów do plików (swoją drogą najlepsza implementacja tego mechanizmu z jaką się do tej pory spotkałem). Jest odpowiedni plik zawierający definicję routingu.

Zajmijmy się jednak w pierwszej kolejności konfiguracją output types:

XML:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <output_type name="html">
  3.   <renderer class="AgaviPhpRenderer" extension="tpl.php">
  4.     <parameters>
  5.       <parameter name="assigns">
  6.         <parameters>
  7.           <parameter name="routing">r</parameter>
  8.           <parameter name="request">req</parameter>
  9.           <parameter name="controller">ctl</parameter>
  10.           <parameter name="user">usr
  11.           </parameter>
  12.           <parameter name="translation_manager">tm</parameter>
  13.         </parameters>
  14.       </parameter>
  15.       <parameter name="i18n">
  16.         <parameters>
  17.           <parameter name="mode">subdir</parameter>
  18.         </parameters>
  19.       </parameter>
  20.     </parameters>
  21.   </renderer>
  22.   <parameters>
  23.     <parameter name="Content-Type">
  24.     text/html; charset=UTF-8
  25.     </parameter>
  26.   </parameters>
  27. </output_type>
  28.  
  29. <output_type name="json">
  30.   <renderer class="AgaviPhpRenderer" extension="js.php"
  31.     ignore_slots="true" ignore_decorators="true">
  32.     <parameters>
  33.       <parameter name="Content-Type">
  34.         text/javascript; charset=UTF-8
  35.       </parameter>
  36.     </parameters>
  37.   </renderer>
  38. </output_type>

Jak widać trochę tej konfiguracji jest, nie mniej celowo usunąłem przekazywanie parametrów do drugiego formatu wynikowego by pokazać, że w najskromniejszej wersji definicja taka potrafi się zmieścić maksymalnie w 10 linijkach.
Do wszystkich parametrów możemy odwoływać się w widoku. Specyficzne są parametry o nazwie assigns oraz i18n. Pierwszy z nich Agavi wykorzysta po to by od razu w fazie tworzenia renderera wrzucić do niego wskazane obiekty, które znajdują się w kontekście. Drugi z atrybutów jest szczególnie przydatny podczas tworzenia aplikacji z wieloma językami. Parametr i18n jest prefiksem dla nazwy pliku. W przypadku gdy przypiszemy mu wartość subdir framework będzie szukał szablonów po katalogach np. pl/IndexSuccess, en/IndexSuccess. Inne, dopuszczalne wartości to postfix oraz prefix. Nazwy szablonów to odpowiednio IndexSuccess_pl oraz pl_IndexSuccess
Atrybut extension określa suffix dla nazwy pliku, którego użyje Agavi przy wczytywaniu szablonu np IndexSuccess.tpl.php.
Argumenty ignore_slots oraz ignore_decorators odnoszą się do strategii budowania widoku. W chwili gdy zrezygnujemy z nich wynik nie będzie dekorowany. Tzn. w odpowiedzi użytkownik zobaczy tylko treść wygenerowaną przez widok akcji.
Tutaj drobna uwaga. W wersji stabilnej Agavi 0.11 mechanizm ten zachowuje się nieco inaczej. Wybór plików oraz zachowanie dekoratora determinuje layout i elementy layer.

Następnie w routes.xml dla każdej ścieżki możemy określić również format wynikowy danych. Np:

XML:

  1. <route pattern="/ajax$" output_type="json" stop="false" />

W tym momencie, wszystkie adresy kończące się na /ajax będą obsługiwane w nieco inny sposób niż pozostałe. To znaczy, że nie będzie dekorowany output. Dodatkowo zostaną użyte inne pliki szablonów do generowania treści.

Zdaję sobie sprawę z tego, że opisałem ten mechanizm dość chaotycznie i bardziej skupiłem się na jego konfiguracji, ale na przykładową aplikację będziecie musieli poczekać do czasu gdy skończę artykuł dla PHP Solutions (czyżby Agavi tematem numeru?) bądź do pojawienia się nowego Code-House. :)

2 responses so far

2 Responses to “Agavi, Output types”

  1. Wojtek says:

    Grejt artykuł :)
    PS. Proponuję uciąć i dać read more... szukając innych notek krew zalewa jak musisz tyle nakręcić się pokrętłem.

  2. [...] stąd klasa widoku to CartProductView). Co więcej w połączeniu z innym mechanizmem Agavi, Output types, zmiany formatu widoku oraz języka nie wiążą się z implementacją bądź powielaniem logiki [...]

Leave a Reply