PHPTAL jest implementacją pythonowskiego systemu Zope Page Template w języku PHP. Jego cechą charakterystyczną odróżniającą go od Smarty jest to, że zmienne występują wyłącznie w atrybutach znaczników. Poznanie biblioteki PHPTAL pozwala spojrzeć na podział przetwarzanie/ prezentacja z nieco węższej perspektywy.
Instalacja i pierwszy skrypt
Biblioteka PHPTAL jest rozpowszechniana w postaci
spakowanego archiwum {stala}latest.tar.gz{/stala}. Po rozpakowaniu
archiwum otrzymamy plik {stala}PHPTAL.php{/stala}
oraz folder PHPTAL/. Instalacja pakietu PHPTAL sprowadza
się do umieszczenia pliku {stala}PHPTAL.php{/stala} oraz
folderu {stala}PHPTAL/{/stala} w miejscu zawartym w ścieżkach
dostępu, np.:
C:\php\PEAR\PHPTAL.php
C:\php\PEAR\PHPTAL\
Skrypt stosujący szablony PHPTAL składa się
z dwóch plików: {stala}index.php{/stala} oraz {stala}sz.html{/stala}. Pliki te
należy umieścić w tym samym folderze. Plik index.
php zawiera instrukcję dołączającą bibliotekę {stala}PHPTAL{/stala},
utworzenie obiektu {stala}$template{/stala} oraz instrukcje
przetwarzające szablon:
execute();
}
catch (Exception $e){
echo $e;
}
?>
Parametrem konstruktora {stala}PHPTAL(){/stala} jest nazwa
pliku z szablonem. Plik {stala}sz.html{/stala} zawiera kod HTML
strony powitalnej:
Witaj
Zmienne
Przekazywanie zmiennych
W bibliotece PHPTAL zmienne szablonu są przekazywane
jako właściwości obiektu {stala}$template{/stala}:
$template->tytul = \'Lorem ipsum\';
$template->tekst = \'Dolor sit amet\';
lub poprzez wywołanie metody {stala}set(){/stala}:
$template->set(\'tytul\', \'Lorem ipsum\');
$template->set(\'tekst\', \'Dolor sit amet\');
W szablonie {stala}sz.html{/stala} dostęp do zmiennych uzyskujemy
stosując nazwę właściwości:
tytuł zastępczy
treść zastępcza
Jeśli do szablonu przekażemy zmienną o nazwie
abc i wartości abecadło:
$template->abc = \'abecadło\';
to w szablonie operujemy nazwą abc, podając ją
jako wartość atrybutu {stala}tal:content{/stala}:
xyz
Powyższy znacznik spowoduje zastąpienie tekstu
xyz napisem abecadło (tj. treść elementu p zostanie
zastąpiona wartością zmiennej o nazwie abc).
Wygenerowany zostanie następujący kod HTML:
abecadło
Zwróćmy uwagę, że tekst xyz pomiędzy znacznikami {html}
oraz
{/html} może być dowolny, gdyż ulega
zamianie.
Atrybuty
Wartości atrybutów
Wartości atrybutów znaczników HTML ustalamy wykorzystując
{stala}tal:attributes{/stala}. Ze skryptu index.php do
szablonu przekazujemy wartość atrybutu:
$template->url = \'lorem.html\';
Natomiast w szablonie wywołujemy {stala}tal:attributes{/stala},
podając nazwę atrybutu (href) oraz nazwę
zmiennej (url), która ma być użyta jako wartość:
...
Kilka atrybutów
Pojedynczy znacznik HTML może zawierać kilka
atrybutów. W takiej sytuacji atrybut {stala}tal:attributes{/stala}
zawiera kilka wpisów oddzielonych średnikiem. Do
szablonu przekazujemy zmienne klasa oraz identyfikator:
$template->klasa = \'naglowek\';
$template->identyfikator = \'glowny\';
W szablonie w atrybucie {stala}tal:attributes{/stala} wymieniamy
zarówno class, jak i id, podając nazwy zmiennych,
które mają być użyte jako wartości:
lorem
Powyższy szablon wygeneruje kod:
lorem
Składanie wartości atrybutu z kilku zmiennych
Niekiedy atrybut HTML może powstawać z kilku
zmiennych przekazanych do szablonu. W takiej sytuacji
wykorzystujemy modyfikator string.
Do szablonu przekazujemy etykietę hiperłącza,
folder oraz fragment nazwy pliku:
$etykieta = \'Dolor sit amet\';
$folder = \'fld/dir/\';
$url = \'lorem.html\';
$template->etykieta = $etykieta;
$template->folder = $folder;
$template->url = $url;
Na bazie tych trzech zmiennych należy wygenerować
odnośnik:
Dolor sit amet
W PHP zadanie to realizują instrukcje:
echo \'\';
echo $etykieta;
echo \'\';
W szablonie PHPTAL należy wykorzystać atrybuty
{stala}tal:content{/stala} oraz {stala}tal:attributes{/stala} w następujący
sposób:
a
Podsumowanie
Główną przyczyną umieszczenia instrukcji przetwarzania
szablonu w atrybutach HTML była – jak podaje
dokumentacja – chęć stosowania edytorów
wizualnych. Argument ten wydaje się ważny wyłącznie
dla osób pracujących w programach WYSIWYG.
Jako zwolennik ręcznego pisania kodu (PHP/HTML/CSS) nie uznałbym tego za ważny plus. Jednak
z takiego podejścia wynikają inne, moim zdaniem
ważniejsze, korzyści:
- silniejsze wymuszenie programowania obiektowego,
- bardziej rygorystyczna niż to ma miejsce na przykład
w przypadku Smarty separacja przetwarzania
od prezentacji.
Dokumentacja PHPTAL jawnie zaleca stosowanie
obiektów oraz korzystanie z metod, które decydują
o przetwarzaniu szablonu. W miejsce wyrażeń
osadzanych w szablonie:
...
zalecane jest zdefiniowanie metody {stala}hasMoreThan-FiveItems(){/stala}:
...
W ten sposób zawartość szablonu sprowadzi
się do odczytywania właściwości i wywoływania
metod obiektów przekazanych do szablonu. Podejście
takie zastosowane w odniesieniu do wszystkich
aspektów szablonu spowoduje, że atrybuty
(m.in. href hiperłączy) będą także przekazywane
jako właściwości lub zwracane przez metodę.
W miejsce:
a
pojawi się:
a
Mimo że pozostanę użytkownikiem szablonów
Smarty (głównie z powodu trudności w generowaniu
przy użyciu PHPTAL plików tekstowych oraz LaTeX-a), to uważam, że lekcja wypływająca z poznania
systemu PHPTAL jest bardzo ważna. Uściśla bowiem
zakres obejmowany pojęciami przetwarzanie
oraz prezentacja. Im precyzyjniej określimy wszystkie
cechy prezentacyjne aplikacji, tym łatwiej będzie
w przyszłości wprowadzać zmiany w kodzie.
Rozbicie szablonu na kilka plików
Makrodefinicje
W celu rozbicia dużego szablonu na kilka plików
w PHPTAL stosujemy makrodefinicje. W osobnym
pliku o nazwie {stala}makro-menu.html{/stala} umieszczamy definicję
makra o nazwie {stala}main_menu{/stala}:
W szablonie głównym makro wywołujemy korzystając
z atrybutu {stala}metal:use-macro{/stala}. Wartość atrybutu
zawiera nazwę pliku oraz nazwę makrodefinicji:
Znacznik {html}{/html}, który zawiera wywołanie
makra, jest automatycznie usuwany. Nie pojawia
się on w generowanym kodzie HTML. Ponieważ tak
zapisany znacznik span jest niepoprawny, lepiej do
wywoływania makr stosować br:
Przekazywanie zmiennych do makr
Wszystkie zmienne przekazane do szablonu, np.
tytul oraz opcje:
$template->tytul = \'lorem ipsum\';
$template->opcje = array(\'dolor\', \'sit\');
są automatycznie dostępne wewnątrz makr. Makrodefinicja
menu zawarta w pliku {stala}makro-menu.html{/stala}
wykorzystuje obie zmienne tytul oraz opcje:
...
- ...
Obiekty
Dostęp do pól obiektów
Do przekazywania złożonych danych dokumentacja
PHPTAL zaleca stosowanie klas i obiektów. Po
zdefiniowaniu klasy Osoba:
class Osoba
{
public $imie;
public $nazwisko;
function_construct($AImie, $ANazwisko)
{
$this->imie = $AImie;
$this->nazwisko = $ANazwisko;
}
}
do szablonu przekazujemy obiekt o nazwie student:
{stala}$template->student = new Osoba(\’Jan\’, \’Kowalski\’){/stala}
W szablonie publiczne pola obiektu są dostępne
jako: student/imie oraz student/nazwisko:
...
...
Obiekty Propel
W przypadku obiektów generowanych przez oprogramowanie
Propel dostęp do pól jest realizowany
metodami {stala}get(){/stala}. PHPTAL pozwala na wywoływanie
dowolnych metod obiektu. Operator -> języka
PHP:
$osoba->getImie()
zostaje w PHPTAL zastąpiony przez kropkę:
$osoba.getImie()
Klasa Osoba ma metody {stala}getImie(){/stala}, {stala}getNazwisko(){/stala},
{stala}getWiek(){/stala} oraz {stala}getPlec(){/stala}. Po przekazaniu do
szablonu tablicy obiektów klasy Osoba:
$template->osoby = OsobaPeer::doSelect(new Criteria);
stosujemy iterację {stala}tal:repeat{/stala}. W kolejnych obrotach
wywołujemy metody dostępu do pól obiektu o:
Oczywiście uruchomienie tego przykładu wymaga
instalacji bazy danych wypełnionej rekordami.
Zadanie to realizuje skrypt {stala}create-db-filled.bat{/stala}
(należy pamiętać o wprowadzeniu – w miejsce
AX1BY2CZ3 – hasła administratora).
Przykłady
ABBA
Pierwszy przykład, strona z piosenkami zespołu
ABBA, powstaje na podstawie plików tekstowych.
W skrypcie {stala}index.php{/stala} przetwarzamy pliki tekstowe.
Całość odczytanych informacji przekazujemy do szablonu
jako obiekt o nazwie menu – patrz listing 1.
class MenuItem
{
public $url;
public $caption;
function __construct($aurl, $acaption)
{
$this->url = $aurl;
$this->caption = $acaption;
}
}
class Menu
{
private $ile;
private $numer;
public $tytul;
public $tekst;
public $piosenki;
function __construct()
{
$plik = file(\'dane/00lista.log\');
$this->ile = count($plik);
$this->numer = 0;
if (isset($_GET[\'id\']) && str_ievpifr($_GET[\'id\'], 1, $this->ile)) {
$this->numer = $_GET[\'id\'] - 1;
}
$tmp = explode(\':\', trim($plik[$this->numer]));
$nazwaPlikuWybranego = $tmp[1];
$this->tytul = $tmp[0];
$this->tekst = file_get_contents(\'dane/\' . $nazwaPlikuWybranego);
$this->piosenki = array();
for ($i = 0; $i < $this->ile; $i++) {
$linia = explode(\':\', trim($plik[$i]));
$this->piosenki[$i] = new MenuItem(\'index.php?id=\' . ($i + 1), $linia[0]);
}
}
}
$template = new PHPTAL(\'templates/sz.html\');
$template->menu = new Menu;
try {
echo $template->execute();
} catch (Exception $e){
echo $e;
}
Obiekt ten ma następujące właściwości:
$menu->tytul
$menu->tekst
$menu->piosenki[]
$menu->piosenki[n]->url
$menu->piosenki[n]->caption
Dwie pierwsze właściwości, {stala}$menu->tytul{/stala} oraz
{stala}$menu->tekst{/stala}, zawierają dane piosenki wybranej
z menu. Właściwość {stala}$menu->piosenki[]{/stala} jest tablicą,
która zawiera wszystkie opcje menu. Każda
z opcji ma właściwość {stala}$menu->piosenki[n]->url{/stala}
oraz {stala}$menu->piosenki[n]->caption{/stala}. W szablonie
{stala}sz.html{/stala} najpierw ustalamy tytuł strony:
...
następnie drukujemy menu:
po czym wyświetlamy tytuł i tekst wybranej piosenki:
...
...
Ptaki
Drugi przykład jest bardziej skomplikowany. Witryna
\”Ptaki\” udostępnia zawartość bazy danych.
Całość jest zaimplementowana przy użyciu Propela.
Uruchomienie przykładu należy rozpocząć od
instalacji bazy danych. Zadanie to realizuje skrypt
zrzut-db.bat, w którym wystarczy wymienić hasło
administratora MySQL. Co ciekawe, wymiana systemu
Smarty na PHPTAL sprowadziła się do kilku
banalnych zmian w kodzie index.php.
Jak widać na listingu 2, wymieniona została
jedna instrukcja {stala}require_once{/stala}, instrukcje przekazujące
dane do szablonu oraz sposób wyświetlania
szablonu.
//require_once \'Smarty.class.php\';
require_once \'PHPTAL.php\';
...
case 4:
$c = new Criteria;
$c->addAscendingOrderByColumn(RodzinaPeer::RODZINA);
$rodziny = RodzinaPeer::doSelect($c);
// $s->assign(\'rodziny\', $rodziny);
$template->rodziny = $rodziny;
break;
...
//$s->assign(\'akcja\', $akcja);
//$s->assign(\'folder\', $folder);
$template->akcja = $akcja;
$template->folder = $folder;
//$s->display(\'index.tpl\');
try {
echo $template->execute();
} catch (Exception $e){
echo $e;
}
Przygotowanie szablonu PHPTAL było znacznie
trudniejsze. W szablonie głównym index.html warunkowo
wywołujemy jedną z makrodefinicji zapisanych
w plikach {stala}home.html{/stala}, {stala}ptaki.html{/stala}, {stala}rodziny.html{/stala}, {stala}ptak.html{/stala}:
Każda z makroinstrukcji stosuje zmienne przekazane
do szablonu. Zmienne te są obiektami Propel
lub tablicami obiektów. Na przykład makroinstrukcja
rodziny.html/rodziny przetwarza tablicę
zawierającą obiekty klasy Rodzina. Obiekty te
mają metody:
- {stala}getUrl(){/stala} – zwraca adres strony WWW
- {stala}getRodzina(){/stala} – zwraca nazwę rodziny
Makrodefinicja przyjmuje więc postać:
Zmienna o nazwie {stala}$folder{/stala} jest konieczna z powodu
użycia względnych przyjaznych URL-i.
Zmienna osadzona w napisie
Zmienna może zostać osadzona w dowolnym napisie.
Treścią elementu HTML zostaje wówczas napis, w którym
występują zmienne. W skrypcie {stala}index.php{/stala} przekazujemy
do szablonu zmienną o nazwie cena:
$template->cena = \'659\';
Zmienna $cena zostaje osadzona w napisie
Cena wynosi … złotych przy użyciu modyfikatora
wyrażeń string:
...
Zmienne zawierające kod HTML
Należy pamiętać, że wartości zmiennych są przed
wydrukowaniem automatycznie zabezpieczane
wywołaniami {stala}htmlspecialchars(){/stala}. Jeśli do szablonu
przekażemy zmienną:
$template->tekst = \'Lorem ipsum
\';
to znacznik:
...
spowoduje wydrukowanie tekstu, w którym znaki {html}<{/html} oraz {html}>{/html} są zastąpione przez {html}<{/html} i {html}>{/html}:
Lorem ipsum
Jeśli chcemy uniknąć konwersji kodu HTML, należy
skorzystać z modyfikatora structure:
...
Wówczas wygenerowany zostanie następujący
kod HTML:
Lorem ipsum
Przekształcanie zmiennych
Zmienne drukowane w szablonie mogą – przed
wydrukowaniem – być poddane dowolnym przekształceniom.
Modyfikacje wykonujemy wywołując
funkcje PHP. Najpierw przekazujemy do szablonu
zmienną o nazwie tytul:
$template->tytul = \'Lorem ipsum...\';
W szablonie stosujemy modyfikator php w połączeniu
z modyfikatorem structure:
...
...
Tablice asocjacyjne
W przypadku użycia tablic asocjacyjnych:
$t = array(\'imie\' => \'Andrzej\',\'nazwisko\' => \'Nijaki\');
$template->osoba = $t;
w szablonie stosujemy odwołania w postaci zmienna/
indeks, np.:
abc
abc
Rezygnacja ze znacznika
Niekiedy może się zdarzyć, że element PHPTAL wymusza
umieszczenie w kodzie HTML dodatkowych
znaczników. Instrukcja:
...
spowoduje wyświetlenie zmiennej tekst wewnątrz
znaczników {html}
{/html}:
...treść zmiennej tekst...
W celu usunięcia elementu div z generowanego
kodu HTML należy użyć atrybutu tal:omit-tag:
...
W takiej sytuacji generowany kod HTML nie będzie
zawierał znaczników {html}
{/html}.
Warunkowe przetwarzanie fragmentu szablonu
Rolę instrukcji if w szablonach PHPTAL pełni atrybut
{stala}tal:condition{/stala}. Jeśli zmienna liczba przekazana
do szablonu przyjmuje wartość logiczną true:
$template->liczba = 15;
wówczas treść elementu div pojawi się w wygenerowanym
kodzie HTML:
...
Atrybut {stala}tal:condition{/stala} może zawierać warunki
logiczne porównujące wartości zmiennych. W takim
przypadku operatory {html}<, <=, >{/html} oraz {html}>={/html} należy
zastąpić przez LT, LE, GT i GE odpowiednio, np.:
Lorem...
Pellentesque...
Iteracyjne przetwarzanie tablic
Pętla pojedyncza
Iteracyjne przetwarzanie tablic umożliwia atrybut tal:
repeat o składni przypominającej instrukcję foreach.
Do szablonu przekazujemy tablicę jednowymiarową.
Zmienna szablonu nazywa się owoce:
$t = array(\'malina\', \'wiśnia\');
$template->owoce = $t;
W szablonie umieszczamy atrybut {stala}tal:repeat{/stala}
o wartości owoc owoce:
- ...
Powoduje on przetworzenie wszystkich elementów
tablicy owoce. W poszczególnych obrotach
pętli do kolejnego elementu tablicy odwołujemy
się stosując nazwę owoc. Zapis:
tal:repeat=\"owoc owoce\" tal:content=\"owoc\"
jest analogiczny do:
foreach ($owoce as $owoc) {
echo $owoc;
}
Indeksy obrotów pętli
Dostęp do indeksów pętli zapewniają specjalne odwołania
postaci:
repeat/x/index
repeat/x/number
repeat/x/even
repeat/x/odd
repeat/x/start
repeat/x/end
W miejsce x należy umieścić nazwę elementu
pętli, na przykład owoc:
Zmienne te mogą być osadzane w napisach
przy użyciu modyfikatora string. Oto w jaki sposób
możemy po numerze kolejnego elementu (dostępnego
jako repeat/owoc/number) dodać kropkę:
...
...
Pętla podwójna
Tablice dwuwymiarowe przetwarzamy w podwójnej
pętli {stala}tal:repeat{/stala}. Po przekazaniu do szablonu
zmiennej elementy:
$t = array(
array(\'ala\', \'ola\', \'jola\', \'tola\'),
array(\'marek\', \'jurek\'),
);
$template->elementy = $t;
stosujemy zagnieżdżoną pętlę tal:repeat:
-
-