Heavymind
Gdyby ludzie rozmawiali tylko o tym, co rozumieją, zapadłaby nad światem wielka cisza.

19/07/2008

Zend Framework Tutorial - Rozwijanie Zend View - Implementacja Smarty

Opublikowane jako: Off topic — Kubek Bartosz @ 17:55

Zend Framework Tutorial

cześć IV

Rozwijanie Zend View :

Implementacja Smarty

Kubek Bartosz, www.heavymind.net
Wersja dokumentu 1.2
Copyright © 2008

Witam w kolejnej części artykułu “Zend Framework Tutorial”. Tak jak to zostało zapowiedziane w poprzedniej części samouczka, również i ten traktować będzie o tej części aplikacji MVC napisanej w oparciu o Zend Framework, która skupia się na wyświetlaniu wyników : widoku, a w przypadku tego artykułu : systemie szablonów HTML: Smarty. Zapraszam.

UWAGA: Ten samouczek wymaga znajomości zagadnień z pierwszej, drugiej i najlepiej trzeciej części serii: “Pierwsze kroki z Zend Framework”, “Zend Framework Tutorial - Rozwijanie Aplikacji” oraz “Zend Framework Tutorial - Rozwijanie Zend View - Zend Layout”.Posiadać również należy działającą aplikację testową z trzeciej części serii. Przykłady zawarte w tym dokumencie, przetestowane zostały w oparciu o Zend Framework w wersji 1.5.1. Najprawdopodobniej będą działały także z nowszymi wersjami, jednak jest mało prawdopodobne, by prawidłowo mogły być uruchamiane z wersjami wcześniejszymi niż wersja 1.5.0.

Spis treści:

Wprowadzenie

Niejednokrotnie, architekci systemów działających na bazie języka PHP decydują się, by sposób w jaki będą przygotowywane szablony HTML, w czym zawiera się programowanie ich by przyjmowały i wyświetlały dane z aplikacji PHP - uprościć do maksimum. Celem ich staje się wtedy chęć zapewnienia grafikom i webmasterom recepty na łatwą i sprawną komunikację z developerami PHP. Tak by w efekcie paczki danych jakie programista przekazuje do szablonu HTML nie wymagały drastycznych jego zmian i przeróbek, oraz tak by grafik/webmaster nie był zmuszony do poznawania podstaw języka PHP (bądź nawet obiektowości) po tym jak programista umieści swoją logikę i dane w szablonie. Rozwiązaniem takich sytuacji są silniki szablonów. Znanymi m.in są Smarty, Pear IT / Pear Sigma, Open Power Template. Na łamach tego artykułu zajmiemy się tym pierwszym.

Naszym celem będzie instalacja silnika Smarty w projekcie testowym, znanym z wcześniejszych części samouczka, integracja Smarty z Zend Frameworkiem, a w zasadzie z Zend_View, oraz w finale przebudowanie naszej aplikacji testowej, tak by funkcjonowała z wykorzystaniem Smarty.

Chciałbym zwrócić uwagę, iż celem tego artykułu nie jest przedstawienie podstaw teoretycznych i praktycznych pracy z systemem szablonów Smarty. Zakładam, iż znasz drogi czytelniku podstawy instalacji i korzystania z Smarty w projektach PHP. Jeśli jednak nie, nic nie stoi na przeszkodzie by zapoznać się z Smarty już teraz. Jest to prosty i intuicyjny system szablonów. Więcej informacji na stronie projektu Smarty.

Instalacja

Na tym etapie naszego projektu testowej aplikacji, powinniśmy posiadać następującą strukturę katalogów:

zf-tutorial/
   /application
      /controllers
      /models
      /views
         /filters
         /helpers
         /scripts
   /library
      /Album
      /Zend
   /public
      /styles

Pozwoliłem sobie przypomnąć ten układ, ponieważ pierwszym krokiem jaki uczynimy, będzie rozszerzenie go o strukturę katalogów, która jest niezbędna dla poprawnego działania systemu szablonów Smarty.
Utwórzmy więc następujące katalogi:

/application/views/templates   // miejsce gdzie trzymane będą szablony HTML
/cache                         // główny katalog cache
/cache/cache_smarty            // katalog plików cache silnika Smarty
/cache/templates_c             // katalog plików cache szablonów Smarty
/library/Smarty                // katalog w którym umieścimy silnik Smarty

Po utworzeniu powyższych katalogów powinniśmy otrzymać poniższą strukturę:

 zf-tutorial/
   /application
      /controllers
      /models
      /views
         /filters
         /helpers
         /scripts
         /templates
   /cache
      /cache_smarty
      /templates_c
   /library
      /Album
      /Smarty
      /Zend
   /public
      /styles

W tym momencie gotowi jesteśmy by pobrać najaktualniejszą wersję Smarty z strony projektu: http://www.smarty.net/download.php . W czasie pisania artykułu była nią wersja 2.6.19. Należy pobrać archiwum ( .zip lub .tar.gz ) i rozpakować go w dowolnej lokacji na dysku twardym. Z rozpakowanej wersji plików i katalogów na dysku, dla nas ma znaczenie zawartość pod-folderu /libs. W folderze tym znajduje się m.in. plik Smarty.class.php.

Całą zawartość katalogu /libs skopiujmy do katalogu /library/Smarty naszego projektu, tak by m.in. plik Smarty.class.php znajdywał się w lokacji: /library/Smarty/Smarty.class.php. Po tej operacji silnik szablonów został osadzony. Należy go teraz podłączyć.

Integracja z Zend_View, czyli praktyczne wykorzystanie “interfejsów”

Dla osób które poświęciły już dodatkowy czas na studiowanie API Zend Framework, oczywistym jest iż napisany on został w oparciu o bardzo eleganckie i nowoczesne (PHP5) wzorce i konstrukcje projektowe. Przy tej okazji celowo nadmienię jedną z nich, którą jest implementacja interfejsów. Słowem teorii: różne klasy (obiekty), które przedstawiają sobą pewną jednakową funkcjonalność, która to funkcjonalność ze względu na cel zastosowania tych klas musi być zapewniona – klasy te mogą, a w zasadzie powinny implementować wspólny interfejs, tj. ogólną, niesprecyzowaną definicję wszelkich funkcji wymaganych do osiągnięcia celu.

W taki właśnie sposób zbudowany jest m.in. Zend_View_Interface – klasa, która definiuje wyłącznie listę minimalną metod, jakie powinna zawierać klasa generująca widok w aplikacji Zend Framework. Jest to jeden z wielu interfejsów jakie są zdefiniowane w tym frameworku, co czyni go takim potężnym, w sensie skalowalności, narzędziem.

Nie powinno być żadnym zaskoczeniem, że klasa główna widoku Zend_View, wraz z jej klasą bazową Zend_View_Abstract implementują interfejs Zend_View_Interface.

Przy tej okazji pojawiło się nam także pojęcie klasy abstrakcyjnej. Tego typu klasa jest także elementem podstawowym obiektowego oblicza PHP5. Zrozumienie tego elementu nie jest wymagana na potrzeby tego artykułu. Jeśli jednak jest Ci, drogi czytelniku, obcy ten termin, pozwolę sobie odesłać Cię do zewnętrznych źródeł.

Dzięki implementacji interfejsu, podczas wykonywania programu PHP, interpreter kodu upewnia się, iż wszystkie wymagane przez Zend_View_Interface metody do poprawnej obsługi widoków (takie jakie zostały zaplanowane przez twórców frameworka, a dokładniej architektów struktury widoków), są zapewnione w klasach do tego celu napisanych, czyli: Zend_View/Zend_View_Abstract.

Całe to słowo wstępu, powinno dać nam jasne uzasadnienie tego, dlaczego w naszej próbie implementacji Smarty do Zend Framework, powinniśmy wykorzystać implementację interfejsu. Otóż jest to najwłaściwsza droga, by podczas pisania naszej klasy (która ma się zająć generacją widoku w naszej aplikacji z wykorzystaniem silnika Smarty), zapewnić jej wszystkie wymagane metody, potrzebne by osiągnąć cel. Klasę naszą nazwiemy Album_View_Smarty.

Wzorzec potrzebnej nam klasy, można znaleźć w dokumentacji Zend Framework tutaj, przy czym proponowana klasa wymaga małego rozszerzenia o pewne nieuwzględnione tam, a bardzo ważne funkcje. Dlatego też poniżej przedstawiam niemal kopię w/w, jednak wzbogaconą:

plik: /library/Album/View/Smarty.php

<?php
require_once 'Zend/View/Interface.php';
require_once 'Smarty/Smarty.class.php';

class Album_View_Smarty implements Zend_View_Interface
{
   /**
    * Smarty object
    * @var Smarty
    */
   protected $_smarty;

   /**
    * Constructor
    *
    * @param string $tmplPath
    * @param array $extraParams
    * @return void
    */
   public function __construct($tmplPath = null, $extraParams = array())
   {
      $this->_smarty = new Smarty;

      if (null !== $tmplPath) {
         $this->setScriptPath($tmplPath);
      }

      foreach ($extraParams as $key => $value) {
         $this->_smarty->$key = $value;
      }
   }

   /**
    * Return the template engine object
    *
    * @return Smarty
    */
   public function getEngine()
   {
      return $this->_smarty;
   }

   /**
    * Set the path to the templates
    *
    * @param string $path The directory to set as the path.
    * @return void
    */
   public function setScriptPath($path)
   {
      if (is_readable($path)) {
         $this->_smarty->template_dir = $path;
         return;
      }
      throw new Exception('Invalid path provided :' . $path);
   }

   /**
    * Set the path to the copile directory
    *
    * @param string $path The directory to set as the path.
    * @return void
    */
   public function setCompilePath($path)
   {
      if (is_readable($path)) {
         $this->_smarty->compile_dir   = $path;
         return;
      }
      throw new Exception('Invalid path provided :' . $path);
   }

   /**
    * Set the path to the smarty cache directory
    *
    * @param string $path The directory to set as the path.
    * @return void
    */
   public function setCachePath($path)
   {
      if (is_readable($path)) {
         $this->_smarty->cache_dir   = $path;
         return;
      }
      throw new Exception('Invalid path provided :' . $path);
   }

   /**
    * Set the path to the smarty configs directory
    *
    * @param string $path The directory to set as the path.
    * @return void
    */
   public function setConfigPath($path)
   {
      if (is_readable($path)) {
         $this->_smarty->config_dir   = $path;
         return;
      }
      throw new Exception('Invalid path provided :' . $path);
   }

   /**
    * Retrieve the current template directory
    *
    * @return string
    */
   public function getScriptPaths()
   {
      return array($this->_smarty->template_dir);
   }

   /**
    * Alias for setScriptPath
    *
    * @param string $path
    * @param string $prefix Unused
    * @return void
    */
   public function setBasePath($path, $prefix = 'Zend_View')
   {
      return $this->setScriptPath($path);
   }

   /**
    * Alias for setScriptPath
    *
    * @param string $path
    * @param string $prefix Unused
    * @return void
    */
   public function addBasePath($path, $prefix = 'Zend_View')
   {
      return $this->setScriptPath($path);
   }

   /**
    * Assign a variable to the template
    *
    * @param string $key The variable name.
    * @param mixed $val The variable value.
    * @return void
    */
   public function __set($key, $val)
   {
      $this->_smarty->assign($key, $val);
   }

   /**
    * Retrieve an assigned variable
    *
    * @param string $key The variable name.
    * @return mixed The variable value.
    */
   public function __get($key)
   {
      return $this->_smarty->get_template_vars($key);
   }

   /**
    * Allows testing with empty() and isset() to work
    *
    * @param string $key
    * @return boolean
    */
   public function __isset($key)
   {
      return (null !== $this->_smarty->get_template_vars($key));
   }

   /**
    * Allows unset() on object properties to work
    *
    * @param string $key
    * @return void
    */
   public function __unset($key)
   {
      $this->_smarty->clear_assign($key);
   }

   /**
    * Assign variables to the template
    *
    * Allows setting a specific key to the specified value, OR passing an array
    * of key => value pairs to set en masse.
    *
    * @see __set()
    * @param string|array $spec The assignment strategy to use (key or array of key
    * => value pairs)
    * @param mixed $value (Optional) If assigning a named variable, use this
    * as the value.
    * @return void
    */
   public function assign($spec, $value = null)
   {
      if (is_array($spec)) {
         $this->_smarty->assign($spec);
         return;
      }

      $this->_smarty->assign($spec, $value);
   }

   /**
    * Clear all assigned variables
    *
    * Clears all variables assigned to Zend_View either via {@link assign()} or
    * property overloading ({@link __get()}/{@link __set()}).
    *
    * @return void
    */
   public function clearVars()
   {
      $this->_smarty->clear_all_assign();
   }

   /**
    * Processes a template and returns the output.
    *
    * @param string $name The template to process.
    * @return string The output.
    */
   public function render($name)
   {
      return $this->_smarty->fetch($name);
   }
}
?>

To co dodatkowe, to funkcje: setCompilePath(), setCachePath() oraz setConfigPath() - funkcje do ustawiania pewnych ścieżek konfiguracyjnych, potrzebnych silnikowi Smarty.

Gwoli jasności, zwracam uwagę, iż nasza klasa Album_View_Smarty implementuje (definiuje) wszystkie metody wymagane przez interfejs Zend_View_Interface.

Powyższa klasa, którą zapisać powinniśmy w katalogu /library/Album/View/ jako plik Smarty.php, jest elementem, który zapewnia zgodne z Zend Framework View podejście do obsługi szablonów HTML, z wykorzystaniem silnika Smarty.

Przygotowanie szablonów

Wymiana HTML na TPL

Szablony ( ang. Templates ) HTML przyjęło się oznaczać rozszerzeniem pliku “tpl“. Tak też uczynimy. Zgodnie z wcześniejszymi przygotowaniami struktury katalogów, powinniśmy mieć przygotowany nowy folder na pliki tpl: /application/views/templates. Powinny znaleźć się w nim wszystkie nasze dotychczasowe (z poprzednich części samouczka) pliki szablonów HTML (które znajdują się w katalogu /application/views/scripts ), wraz z zachowaniem struktury katalogów (aktualnie jest tam podkatalog “index” ). Jedyną zmianą jaka powinna być na nich wykonana w tym momencie, to zmiana ręczna rozszerzenia plików z .phtml, na .tpl. W ten oto sposób, otrzymujemy następującą strukturę plików i katalogów (wypiszę te które nas interesują, pominę resztę) :

...
/application
   ...
   /views
      ...
      /scripts
         /index
            _form.phtml
            add.phtml
            delete.phtml
            edit.phtml
            index.phtml
         layout.phtml
      /templates
         /index
            _form.tpl
            add.tpl
            delete.tpl
            edit.tpl
            index.tpl
         layout.tpl

Dla podkreślenia naszych zamiarów, polecam na tym etapie usunąć całkowicie katalog /application/views/scripts z całą jego zawartością. Naszym celem jest pracować na nowych szablonach – dawne nie będą potrzebne.

Implementacja Smarty w szablonach

Nasze pliki widoków, które przygotowaliśmy w nowym katalogu, są nadal napisane w konwencji prezentowania danych, jakiej nauczył nas Zend_View. Jeśli więc chcieliśmy wyświetlić wartość zmiennej zawierającą obiekt albumu, w szczególności dane o nim tj. tytuł (title), pisaliśmy dotychczas :

<?php echo $this->album->title ?>

Jako że Smarty ma własny sposób na prezentację danych, musimy się do niego dostosować w naszych szablonach. Artukuł ten nie ma na celu uczyć podstaw korzystania z Smarty, dlatego też jeśli nie miałeś dotychczas z nim kontaktu, zapraszam wpierw do zapoznania się z podstawami i dokumentacją na stronie projektu. Dla jasności podam tylko wzór zapisu prezentacji danych, zgodny z Smarty, a funkcjonalnie identyczny do w/w przykładu :

{$album->title}

Tak wiec nie potrzeba nam już ciągłego otwierania i zamykania tagów PHP, czy też wykonywania w szablonach funkcji PHP, takich jak echo, czy if lub foreach.

Aby ponownie jasno przedstawić zagadnienie tego pod-rozdziału, poniżej zamieszczam treść wszystkich kolejnych plików szablonów, w których pozamieniane są wszystkie wywołania zmiennych na “Smart’owe”.

plik: /application/views/templates/layout.tpl

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   <head>
      <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
      <title>{$title}</title>
      <link rel="stylesheet" type="text/css" media="screen"
         href="{$baseUrl}/public/styles/style.css" />
   </head>
   <body>
      <div id="content">
         {$layout->content}
      </div>
   </body>
</html>

plik: /application/views/templates/index/index.tpl

   <h1>{$title}</h1>

   <p><a href="{$baseUrl}/index/add">Add new album</a></p>
   <table>
      <tr>
         <th>Title</th>
         <th>Artist</th>
         <th> </th>
      </tr>
      {foreach from=$albums item=album}
      <tr>
         <td>{$album->title}</td>
         <td>{$album->artist}</td>
         <td>
            <a href="{$baseUrl}/index/edit/id/{$album->id}">Edit</a>
            <a href="{$baseUrl}/index/delete/id/{$album->id}">Delete</a>
         </td>
      </tr>
      {/foreach}
   </table>

plik: /application/views/templates/index/_form.tpl

   <form action="{$baseUrl}/index/{$action}" method="post">
      <div>
         <label for="artist">Artist</label>
         <input type="text" name="artist" value="{$album->artist}" />
      </div>
      <div>
         <label for="title">Title</label>
         <input type="text" name="title" value="{$album->title}" />
      </div>
      <div id="formbutton">
         <input type="hidden" name="id" value="{$album->id}" />
         <input type="submit" name="add" value="{$buttonText}" />
      </div>
   </form>

plik: /application/views/templates/index/add.tpl

   <h1>{$title}</h1>
   {include file='index/_form.tpl'}

plik: /application/views/templates/index/delete.tpl

   <h1>{$title}</h1>

   {if $album->id > 0 }
   <form action="{$baseUrl}/index/delete" method="post">
      <p>Are you sure that you want to delete "{$album->title}" by
         "{$album->artist}" ?</p>
      <div>
         <input type="hidden" name="id" value="{$album->id}" />
         <input type="submit" name="del" value="Yes" />
         <input type="submit" name="del" value="No" />
      </div>
   </form>
   {else}
   <p>Cannot find album.</p>
   {/if}

plik: /application/views/templates/index/edit.tpl

   <h1>{$title}</h1>
   {include file='index/_form.tpl'}

Różnice są dość wyraźnie zauważalne, dlatego też pozwalam sobie nie wnikać w detale i porównanie pozostawić Tobie czytelniku.

Finalny krok: integracja z MVC

Reasumując, w tym momencie mamy przygotowaną strukturę katalogów pod pliki “czasu-kompilacji” Smarty, pliki cache’u template’ów Smarty i inne katalogi; posiadamy nową klasę Album_View_Smarty, która zapewni nam prawidłowy przepływ danych pomiędzy kontrolerami akcji, a szablonami smarty; ostatecznie wszystkie dotychczasowe pliki widoków, przerobiliśmy na szablony Smarty’owe.

Jest to moment na wykonanie finalnego ruchu – spięcie wszystkiego razem. A dokładnie, to utworzenie obiektu Album_View_Smarty, skonfigurowaniu go, i przekazanie tego obiektu do “framework’a”, tak by zastąpił domyślny Zend_View i przejął kontrolę na siebie.

Konfiguracja

Nie zapominając po co posiadamy pliki konfiguracyjne, wykorzystajmy ten istniejący w lokalizacji: /application/config.ini aby dopisać na jego końcu kilka linii, które posłużą do późniejszej konfiguracji obiektu Album_View_Smarty. Oto one:

;######################################################################
;# Smarty templates configurtion paths
;#
;######################################################################
   smarty.compile_dir   = ../cache/templates_c/
   smarty.cache_dir     = ../cache/cache_smarty/
   smarty.template_dir  = ../application/views/templates
   smarty.config_dir    = ../application

Linie te wskazują zaledwie na strukturę katalogów jaką przygotowaliśmy sobie pod wykonanie naszego zadania. Można rzecz jasna całą tą strukturę zmieniać/przenosić lokalizację katalogów w inne miejsca. Taka właśnie jest idea plików konfiguracyjnych, by przechowywały te dane o aplikacji, które mogą ulegać zmianie. To wszytko odnośnie konfiguracji Smarty – więcej nam nie trzeba. Powyższy zapis konfiguracji wykorzystamy już w krótce podczas:

Implementacja

Aby trzymać się pewnej konwencji, jaką narzuciliśmy sobie w poprzednich częściach Zend Framework Tutorial, zamianę obiektu widoku na nasz Album_View_Smarty, dokonamy w uwspólnionym dla wszystkich kontrolerów miejscu: głównym kontrolerze akcji: Album_Controller_Action. Plik ten znajduje się w lokalozacji: /library/Album/Controller/Action.

Zacznijmy od wstawenia nowego bloku kodu do funkcji init() naszego głównego kontrolera, po czym omówimy sobie co zawiera. Nowy blok został oznaczony ciemną czcionką i wstawiony pomięcy definicję połączenia z bazą danych, a inicjalizacją widoku layout’owego.

plik: /library/Album/Controller/Action.php, funkcja init():

      // setup database
      $db = Zend_Db::factory(
         $this->obConfig->db->adapter,
         $this->obConfig->db->config->toArray() );
      Zend_Db_Table::setDefaultAdapter($db);

      //setup new view object and view helper
      $view = new Album_View_Smarty();
      $view->setScriptPath($this->obConfig->smarty->template_dir);
      $view->setCompilePath($this->obConfig->smarty->compile_dir);
      $view->setCachePath($this->obConfig->smarty->cache_dir);
      $view->setConfigPath($this->obConfig->smarty->config_dir);
      $this->view = $view;

      $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(’viewRenderer’);
      $viewRenderer
         ->setView($view)
         ->setViewSuffix(’tpl’);

      //use layout view pattern
      $layout = Zend_Layout::startMvc();
      $layout->setViewSuffix(’tpl’);
      $view->assign( ‘layout’, $layout );

   }

Przejdźmy kolejno przez to, co nowe. Najpierw utworzyliśmy nowy obiekt klasy Album_View_Smarty, po czym przekazaliśmy do niego wymagane przez Smarty ścieżki konfiguracyjne (odczytane z obiektu konfiguracyjnego, utworzonego wcześniej). Dodatkowo nowo utworzony obiekt widoku, nadpisaliśmy na ten, który domyślnie został przez Zend Framework utworzony w zmiennej klasy kontrolera $this->view. Najbardziej jednak krytycznym momentem, jest to co dzieje się dalej…

Od jakiegoś czasu ( wersji 1.5.0 bodajże ) Zend Framework został wzbogacony o system “helper’ów” do kontrolerów akcji. Helper’y te możemy pisać sami, przy czym w “komplecie” z całym frameworkiem, jest już kilka dostarczonych, a nawet domyślnie włączonych do pracy z frameworkiem (tj. są już aktywne, a my możemy co najwyżej w kodzie je dezaktywować). Szczegóły znajdują się w dokumentacji “helper’ów akcji”. Co warto jeszcze dodać, to że uruchamianiem kolejnych “helperów”, jak również przetrzymywaniem ich, pobieraniem z stosu, jak i dodawaniem nowych - zajmuje się kolejna specialna klasa zintegrowana z mechanizmem kontrolerów: Zend_Controller_Action_HelperBroker ( dokumentacja tutaj ). To właśnie praca z tym obiektem pozwala nam zarządzać istniejącymi, już zarejestrowanymi w tym obiekcie hepler’ami, a także je zmieniać, lub wyłączać. Sam proces “uruchamiania” kolejnych zarejestrowanych “helperów”, Zend_Controller_Action_HelperBroker wykonuje automatycznie.

Jednym z domyślnie aktywowanych helperów jest Zend_Controller_Action_Helper_ViewRenderer ( dokumentacja tutaj ). Klasa ta, domyślnie aktywowana w HelperBroker’rze, swoją funkcionalnością powoduje m.in. automatyczne utworzenie obiektu widoku Zend_View i przypisanie go do do kontrolerów akcji w postaci właściwości obiektu: $this->view, oraz ustawia domyślne rozszerzenie plików vidoku na *.phtml (pozwoliłem sobie wymienić tylko dwie - nas interesujące - z kilku czynności jakie viewRenderer wykonuje).

I w tym momencie wchodzimy “my”. Jako że viewRenderer stworzył już automatycznie instancję obiektu Zend_View i ją przechowuje w swoim stosie, pobieramy z HelperBroker’a referencję do obiektu helper’a viewRenderer, i nasz wcześniej stworzony nowy obiekt Album_View_Smarty przypisujemy (nadpisując stary) do niego. Również ustawiamy nowe rozszerzenie plików widoku przy tej okazji. Dzięki tej operacji, gdziekolwiek programista będzie chciał pobrać obiekt widoku z viewRenderer’a, poprzez HelperBroker’a, otrzyma właściwy obiekt Album_View_Smarty.

Pozostał nam do omówienia ostatni na listingu blok. Pierwszą linię kodu, dotyczącą inicjalizacji wzorca prezentacyjnego Two Step View, znamy już z poprzedniej części samouczka pt. “Rozwijanie Zend View: Zend Layout“. Następnie informujemy zainicjowany obiekt, iż dla tej aplikacji zdecydowaliśmy się na rozszerzenia “tpl” dla plików zawierających HTML. Niestety Zend_Layout nie pobiera tej informacji automatycznie z viewRenderer’a, który już o tym wie. Dlatego robimy to ponownie, ręcznie. Na koniec, w ostatniej linii przypisujemy cały obiekt Zend_Layout do zmiennej Smarty: ‘layout‘, dzięki czemu w głównym pliku “layout’u” (znajdującym się w /application/views/templates/layout.tpl ), możemy skorzystać z tego obiektu, do pobrania treści generowanych przez akcje wykonywane w kontrolerach akcji ( “{$layout->content}” ).

Podsumowanie

Na implementację systemu szablonów Smarty do Zend Framework skłądało się kilka kroków: pierwsze w większości proste w logice i w wykonaniu, o raz ostatni, kryjący za sobą więcej już logiki struktury całego frameworka.

Nie mniej jednak, mam nadzieję że całość treści tego artykułu, okazała się Tobie drogi czytelniku zrozumiałą i jasna. Życzę pomyślnego tworzenia szablonów HTML w Smarty.

Repozytorium SVN

Opisywana wyżej aplikacja testowa jest dostępna do pobrania za pośrednictwem systemu kontroli wersji Subversion (SVN), na serwerach udostępnionych przez usługę Google Code. Kod źródłowy kolejnych wersji tego samouczka, które to powstawały ze względu na kolejne wersje Zend Framework, został odpowiednio rozdzielony, na tzw. tagi. Ze względu na aktualność tego artykłu, jest nim póki co jeden:

Aby skorzystać z w/w repozytoriów, należy użyć jednego z istniejących klientów SVN, tj. np.: KSVN (dla KDE linux), TortoiseSVN (dla windows), lub po prostu CLI klienta SVN w *nix systemach.

Kod aplikacji zawarty w repozytorium można także przeglądać poprzez przeglądarkę internetową, umieszczając adres repozytorium w pasku adresu.

Pozdrawiam

Kubek Bartosz



Komentarze: 9 »

  1. […] samouczka z serii Zend Framework Tutorial, została opublikowana. Jest to artykuł pt. “Zend Framework Tutorial - Rozwijanie Zend View - Implementacja Smarty“, do lektury którego serdecznie […]

    Pingback od Zend Framework Tutorial - Implementacja Smarty - Samouczek opublikowany | Heavymind — 19/07/2008 @ 18:03

  2. brak informacji o:

    $layout = Zend_Layout::startMvc();
    $layout->setViewSuffix(’tpl’);
    $view->assign( ‘layout’, $layout );

    dopiero przy ostatnim listingu (wyszarzone), jak to powinno wyglądać. trochę się naszukałem, bo za pierwszym razem nie chciało się uruchomić. trzeba też zwracać uwagę na apostrofy czasami ‘ a czasami`. ja najczęściej czytając artykul kopiowalem ze strony i musialem to poprawiac.

    ps.
    przydałoby się mieć żródło w jednym pliku zip, a nie tylko w odzielnych plikach.

    Komentarz od drobna korekta — 07/08/2008 @ 09:47

  3. W kodzie layout.tpl jest {$base_url} a powinno być {$baseUrl}
    I znowu jakieś czary mary że w /public/index.php zniknęło ustawienie $frontController->setBaseUrl(’/zf-tutorial/’);

    Komentarz od Tomek — 27/09/2008 @ 23:45

  4. Jak zrobic do tego przykladu obsluge bledow 404 itp czyli ErrorController?

    Komentarz od kerlin — 01/10/2008 @ 13:01

  5. Do tej pory nie miałem większego kontaktu z php5… ale wchłaniam treść całkiem szybko. Bardzo dziękuje za tak przystępną treść. Chciałbym jednak wiedzieć kiedy będzie coś na temat sesji??? Pozdrawiam

    Komentarz od Jakub — 21/10/2008 @ 21:57

  6. @”drobna korekta” - dziękuję. Całkowicie pominięty blok kodu. Aktualizacja treści już jest opublikowana

    @Tomek - błąd poprawiony. dziękuję.

    @kerlin oraz Jakub - aktualnie nie wiadomo kiedy pojawi się jakiś materiał dot. wymienionych tematów

    Komentarz od Kubek Bartosz — 27/10/2008 @ 19:24

  7. hm… dodanie smartow do zf mija sie z celem, nie ze sam zf jest opaslym kombajnem to jeszcze spowolnienie go smartami mie ma wiekszego sensu.
    co nie zmienia faktu ze zwolennikom smartow tutorial sie przyda..

    Komentarz od dartur — 01/11/2008 @ 11:19

  8. Dodanie szablonów Smarty zmniejsza wydajność, ale takie szablony są bardziej czytelne niż standardowe widoki oferowane przez Zend_View.

    Komentarz od Łukasz Adamczuk — 21/01/2009 @ 01:30

  9. Wybaczcie, ale Zend_View też jest systemem szablonów, jakkolwiek sobie tego jego twórcy nie nazwą. Smarty, podobnie jak większość przyzwoitych systemów szablonów, kompiluje je ze względów wydajnościowych do kodu PHP i jedyny dodatkowy narzut czasowy podczas odpalania to konieczność sprawdzenia, czy nie został on zmodyfikowany (dwie operacje dyskowe, które często można wyłączyć na serwerze produkcyjnym). Poza tym systemy szablonów w trakcie normalnej pracy robią praktycznie to samo, co Zend_View, czyli gromadzą dane ze skryptu i de facto największy wpływ na wydajność ma objętość i stopień skomplikowania kodu źródłowego. Jeśli podpinamy system szablonów pod Zend_View, spadek wydajności powodowany jest głównie tym, że trzeba ładować dwie biblioteki, zamiast jednej.

    Co więcej, w przypadku systemów szablonów można niekiedy odzyskać część straconej wydajności, ale zależy to już od możliwości tego, co wykorzystujemy. Część z zendowych helperów napisana jest bardzo niewydajnie (np. placeholderLoop() - dla każdej iteracji tworzy osobny widok i w kółko wczytuje ten sam szablon PHP) i wynika to właśnie z faktu, że jest to PHP, a nie coś innego. Tymczasem używając dodatkowego języka, można osiągnąć taki sam efekt, gdyż parser może przetworzyć ładowanie treści pętli w trakcie kompilacji i wygenerować już gotowy, zoptymalizowany kod PHP wolny od tego typu wynalazków, w którym nawet nie ma śladu po załadowaniu treści pętli z innego miejsca…

    A tak w ogóle to wystarczy dodać cache’owanie i problem znika.

    Komentarz od Zyx — 18/04/2009 @ 09:36

Kanał RSS dla tego wpisu. TrackBack URL

Dodaj komentarz

Oparte na WordPress