Dziś jest czwartek, 20 listopada 2008 roku (z kalendarza...)

Zamiennik dla Zend_Layout

Icon

22.08.2008, 15:42

Projekty

Komentarze (9)

Powrót

Robię właśnie pewien projekcik na bazie Zend Frameworka, w którym postanowiłem zrobić rzeczywiste testy Open Power Template'a 2 (przy okazji - do ściągnięcia jest już dev7). Niestety, z nowymi wersjami nie idzie już tak łatwo, jak ongiś z 1.1. Problem sprawia Zend_Layout, którego projektanci wyszli z założenia, że systemy szablonów są za głupie, by potrafić takie zaawansowane rzeczy.

Oczywiście, da się napisać widok bazujący na OPT, który po wstawieniu będzie z Zend_Layoutem współpracować, tylko że takie rozwiązanie jest krzywdzące dla tego pierwszego. Dziedziczenie szablonów, cała idea wyrugowania programowania z szablonów idzie sobie w las tylko dlatego, że cały ZL opiera się na założeniu, że w szablonach właśnie trzeba programować i ostro korzystać z obiektówki. Takie wnioski wyszły z dyskusji czy ewentualny integrator tej biblioteki z frameworkiem opierać na ZL czy nie.

Rozwiązaniem jest stworzenie własnej wersji ZL, w pełni dostosowanej do tego, co ten system szablonów oferuje oraz jak oferuje. Taki system musi:

  1. Umożliwiać prosty wybór layoutu
  2. Obsługiwać łańcuchy akcji
  3. Umożliwiać akcjom definiowanie bloków widocznych tylko w ich własnym szablonie
  4. Posiadać zestaw funkcji, instrukcji i komponentów do integracji z zendowym routerem i innymi niezbędnymi elementami.
  5. Umożliwiać akcjom dodawanie niezbędnych plików JS, znaczników do sekcji HEAD i innych rzeczy w podobny sposób, jak w ZL.
  6. Obsługiwać dziedziczenie szablonów i wszystko, co z nim związane (w tym gałęzie dziedziczenia).

Nie jest to trudne do zrobienia, zwłaszcza jak się zna każdy bajt kodu OPT, lecz należy pomyśleć nad wyglądem samego API tak, by było użyteczne. Od strony głównego szablonu można spodziewać się czegoś takiego:

<?xml version="1.0" ?>
<opt:root escaping="yes">
 <opt:prolog />
 <opt:dtd template="xhtml10transitional />
 <html>
   <head>
     <meta http-equiv="Content-Type" parse:content="$contentType" />
     <opt:generator from="$title" />
     <opt:generator from="$style" />
     <opt:generator from="$script" />
   </head>
   <body>
     <div id="header">
       <h1>Nagłówek strony...</h1>
     </div>
     <div id="left_menu">
       <opt:section name="left_menu">
        <div class="menu">
          <opt:include from="left_menu">
           <p class="error">Oops, nie mogłem załadować {$left_menu.file}</p>
          </opt:include>
        </div>
       </opt:section>
     </div>
     <div id="content">
       <opt:section name="content">
         <opt:include from="content" />
       </opt:section>
     </div>
     <div id="footer">
       <p>Copyright &copy; by Foo {$currentYear}</p>
     </div>
   </body>
 </html>
</opt:root>
 

Wszystkie niezbędne bloki zostaną stworzone przez naszego hipotetycznego przyjaciela Opt_Layout na podstawie danych dostarczonych przez akcje. Szablony poszczególnych akcji mogą swobodnie korzystać z dziedziczenia, co pozwala np. w prosty sposób rozszerzać formularze:

<?php
 
   class FormController extends Zend_Controller_Action
   {
      public function form1Action()
      {
         // forma odwolania jeszcze nieznana, wiec ustalmy $this :)
         $this->setTemplate('content', 'form1.tpl');
      } // end form1Action();
 
      public function form2Action()
      {
         $this->setTemplate('content', 'form2.tpl');
      } // end form2Action();
   }

oraz szablon:

<!-- form1.tpl -->
<opt:root>
  <form method="post">
     <opt:route _type="action" str:controller="form" action="$this.currentAction" />
     Pole 1: <input type="text" name="field1" value="{$form.field1}" />
     Pole 2: <input type="text" name="field2" value="{$form.field2}" />
 
     <opt:insert snippet="formExtension" />
 
     <input type="submit" value="OK"/>
  </form>
</opt:root>
 
<!-- form2.tpl -->
<opt:extend file="form1.tpl">
  <opt:snippet name="formExtension">
    Pole 3: <input type="text" name="field3" value="{$form.field3}" />
  </opt:snippet>
</opt:extend>

Akcja form2 w rzeczywistości korzysta tutaj z szablonu form1.tpl, lecz rozszerzonego o nową funkcjonalność. Dziedziczenie w OPT pozwala na skonfigurowanie gałęzi dziedziczenia (czyli różnych wariantów plików, po których możemy dziedziczyć), a niebawem będzie zezwalać akcjom na samodzielne wybranie nazwy dziedziczonego szablonu.

Oczywiście pełna obsługa formularzy pojawi się wówczas, gdy zacznie powstawać Open Power Forms, jako że integrator byłby później rozbudowywany o kolejne biblioteki, które będą się pojawiać.

Zakończenie

Mam nadzieję, że realizowany projekt pozwoli mi opracować idealne wzorcowe rozwiązanie dla użytkowników Zend Frameworka. Ostatnie trzy miesiące poświęciłem na przeprojektowywanie całej serii bibliotek nie tylko pod kątem integracji jednej z drugą, ale także współpracy z innymi narzędziami, bez których o stworzeniu dużego projektu nie ma obecnie co marzyć.

OPT 2 jest na najlepszej drodze do udowodnienia, że systemy szablonów wcale nie są takie bez sensu, o ile oferują coś więcej, niż zwykłą kalkę PHP. Mamy zaledwie kilka klocków oraz reguł, dzięki którym można zmontować już niemal wszystko bez konieczności programowania, w pełni skupiając się na tym, co chcemy uzyskać. W PHP też da się osiągnąć podobne rezultaty, lecz pewne ograniczenia wpływające na przyjemność użytkowania narzuca sam język. Nowa składnia jest właśnie po to, by te ograniczenia usunąć i pozwolić prosto robić coś, co w PHP jest z natury trudne... do tego dodajmy modne ponowne wykorzystanie kodu. Wklej pętlę foreach z PHP w inne miejsce, to przestanie działać. Wklej sekcję w inne miejsce, ochoczo zabierze się do pracy, nawet jeśli nowa lokalizacja dostarcza jej danych w zupełnie innym formacie. Chcesz mieć to samo w PHP, musisz porządnie zaangażować w sprawę programowanie obiektowe. Przykłady można mnożyć. Dość, by powiedzieć, że dobrze napisany szablon OPT mógłby być nawet wykorzystywany przez Ruby'ego bez zmiany czegokolwiek, gdyby tylko istniał parser dla tego języka... a wszystko to powstało dzięki zjechaniu mnie 3 lata temu za klonowanie Smarty'ego :).

Powrót

Komentarze

Napisał eXtreme w piątek, 22 sierpnia 2008 o 21:35

"projektanci wyszli z założenia, że systemy szablonów są za głupie, by potrafić takie zaawansowane rzeczy."
ROFLMAO :D znasz jakiś system szablonów prócz OPT który by robił coś podobnego? Oni po prostu podeszli do tego racjonalnie. Mają zend_view na PHP i tam po prostu było to potrzebne. I - choćbyś się zes**ł - nie zrobisz tego tak by wszystkim dogodzić. Myślisz, że twórcy ZF słyszeli o jakimś OPT2? Dlaczego więc mięli "wychodzić z założenia", że systemy szablonów to potrafią?

Napisał radziel w sobotę, 23 sierpnia 2008 o 00:23

Czekam z niecierpliwością na stabilną wersję OPT2.

Aktualnie kończę prywatny projekt oparty o ZF - wykorzystuje Zend_View + Zend_Layout i nie jestem z tego rozwiązania w 100% zadowolony. Dlatego chciałbym je zamienić na jakiś system szablonów z prawdziwego zdarzenia :)

Obawiam się tylko jednego - jak będzie wyglądało wsparcie dla zendowskich view/action helperów w szablonie? Mogę liczyć na to, że migracja (w przyszłości) na OPT nie przysporzy poważniejszych problemów? ;-)

Napisał Zyx w sobotę, 23 sierpnia 2008 o 10:25

Jeśli połączysz Zenda z OPT, a jeszcze potem dodasz OPF, to wątpię, by zendowskie helpery na coś się w szablonach przydały, aczkolwiek pomyślę nad jakimś pojemnikiem w formie komponentu, by można było takowe opakować i w miarę łatwo osadzać.

eXtreme -> dziedziczenie co najmniej kilka systemów obsługuje w formie mniej lub bardziej zaawansowanej. Co jeszcze potrzeba? Możliwość umieszczenia include'a w pętli i pisania wtyczek, by nie programować w szablonach, a to nawet słynny Smarty, o którym musieli słyszeć, ma. Tak więc: nie pomyśleli.

Napisał Lucas w poniedziałek, 25 sierpnia 2008 o 07:06

Tak mnie tknęło i zerknąłem do dokumentacji. Niestety się potwierdza. Skoro OPT może być parsowany jako xml to dlaczego tak luźno traktuje przestrzenie nazw? Przykłądowo <opt:generator from="$title" /> -> <opt:generator opt:from="$title" />

Napisał radziel w poniedziałek, 25 sierpnia 2008 o 15:13

> Jeśli połączysz Zenda z OPT, a jeszcze potem
> dodasz OPF, to wątpię, by zendowskie helpery na
> coś się w szablonach przydały

Tutaj akurat się nie zgodzę. Moim zdaniem istnieje grupa pewnych helperów, których raczej nie da się porzucić nie utrudniając sobie kodowania. Niech za przykład posłuży chociażby Url Helper do automatycznego generowania linków na podstawie danych z tablicy lub - co ważniejsze - na podstawie tras zdefiniowanych przez Zend_Controller_Router_Route.

Napisał sapper w poniedziałek, 1 września 2008 o 08:10

Nigdy nie wdaje się w dyskusje co jest lepsze a co nie. Korzystam ZF od początku powstania i wg mnie jest to może nienajlepszy framework, ale najlepsza kopalnia rozwiązań, Patrze na OPT podobnie jak na Smarty to jest kolejna nakładka na PHP do wykorzystania tylko przez projektantów, grafików którzy nie muszą znać PHP. W moim przypadku jestem projektantem, grafikiem, programistą (OOP). Tracenie czasu na poznanie jakieś nakładki jest zbednym czasem ponieważ wszystko powtórze wszystko jestem wstanie zrobić przy wykorzystaniu Zend_View + Zend_Layout + helpery (szybciej). Moja rada poznajcie ZF od środka to zobaczycie jak można lepiej i sprawniej pisać projekty. pozdrawiam.

Napisał Zyx w poniedziałek, 1 września 2008 o 21:18

Ktoś kiedyś porównał programowanie imperatywne do wydawania poleceń idiocie. Ten styl na pewno zapewnia największą kontrolę nad tym, co się dzieje, ale właśnie kosztem wydawania idiotycznie szczegółowych rozkazów. I choćbyś nie wiem, co robił, obiektówką i tak tego do końca nie przeskoczysz. Nowe języki i style programowania powstają, bo ludziom przestają wystarczać dotychczasowe narzędzia. Właśnie z tego korzystam w OPT - dzięki własnemu parserowi, mogę dodać do tej "nakładki" rzeczy, których w PHP nie wykonasz nigdy bez dziesiątek linii kodu właśnie z powodu różnic w paradygmatach programowania. Jeśli wygodnie Ci klepać kod w czystym PHP, nikt Cię nie zmusza do systemów szablonów. Masz do tego prawo. Ale mnie pisanie generatora kodu HTML w czystym PHP okropnie wkurza, choćbym miał nie wiadomo ile narzędzi. Zend_Layouta również się musiałeś nauczyć i tym oto sposobem pada drugi argument: ty nauczyłeś się ZL i piszesz w nim szybko i sprawnie, ja nauczyłem się OPT i też piszę w nim szybko i sprawnie. Dla mnie oba wybory są równoważne, bo skutek jest ten sam.

Z OPT korzystam z tego samego powodu, dla którego ty piszesz oprogramowanie do stron w PHP, a nie w C++ czy w assemblerze.

Napisał Lucas w wtorek, 2 września 2008 o 14:10

Url helper w ZF. Przykładowy adres: /test/123 z restrykcją :id 0-9. Nawet się nie zająknie na podesłanie /test/dupa. To też nie jest doskonałe. Mnie osobiście skręca jak patrzę na Zend_Layout i View. Nie wiem jak można pisać na takiej sieczce - tym bardziej jeżeli ktoś (jak ja) nie lubi stosować short_open_tags. Pomylisz się w szablonie, prześlesz do niego źle zakodowaną encję i hurra, masz rozsypkę. Pewną nadzieję rokuje dodanie w 1.6 Zend_Dom_Query który mógłby być wstępem do Zend_Xml na kształt martwego niestety XT. Ja jakiś czas temu przerzuciłem się z OPT na PHTALa (zwłaszcza że można powiedzieć jest to teraz projekt polski :) ). Szybszy od OPT, mniej pamięciożerny i idealnie współpracuje z ZF. Radzę ci sapper spróbować to zmienisz zdanie. Odpowiesz mi zyx co z tą nieprawidłową składnią xml (wymieszanie NS) w OPT?

Napisał Ash w środę, 22 października 2008 o 05:24

Kurcze, pewnie ja się mylę, ale dla mnie OPT zawsze podchodziło pod nadpisanie klasy Response_http (chyba nie przekręciłem) a nie do stosowania jako zamiennik View.

Owszem wymaga to nadpisania innych klas w Controller (jak Action itp. ale w końcu o taką swobodę chodziło twórcom) ale mogę czerpać "normalnie" z OPT a nie sprowadzać go do poziomu "znajdź i zmień".

To co znalazłem zaproponowane na pl forum ZF, przypomina fasynację corem, a nie próbę osiągnięcia symbiozy bez dublowania funkcjonalności. OPT nigdy moim zdaniem nie przypominało Zend_View i nigdy tego tak nie implementowałem. Bardzo spodobał mi się wpis tutaj, odnośnie separacji danych dla szablonu co pomyślnie działa na produkcji. Dla mnie jest kontener http, jest dokument który ma swoje head i body, a body ma rejony do wpakowania modułów.

Naturalnie kwestia koncepcji. ;)

Strona 1 z 1 :: 1

Skomentuj

NickInformacja
E-mailTylko do użytku wewnętrznego.
WWWNie zapomnij o http://
LayoutNapisz tu, czy widzisz dzienny czy nocny layout.
WpisFormatowanie wiki
Internauto, pamiętaj! Wolność to nie samowola - dbaj o kulturę wypowiedzi oraz dyskusji w sieci.

Na Zyxist.com panuje swoboda wyrażania opinii oraz krytyki pod dowolnym adresem. Jedyny warunek: musi być ona kulturalna i rzeczowa. Na chamstwo, prostactwo lub jawne obrażanie kogokolwiek nie ma tu miejsca i takie komentarze są bardzo szybko usuwane. Jeśli zamierzasz polemizować z treścią wpisu, wpierw uważnie ją przeczytaj.

© Tomasz "Zyx" Jędrzejewski 2005 - 2008 | Wykonanych zapytań: 2 | Serwer wirtualny zapewnia