PHP/Open Power Template: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Zyx (dyskusja | edycje)
m poprawka nawigacji
Zyx (dyskusja | edycje)
rozpoczęcie prac nad przebudową i gruntowną aktualizacją
Linia 1:
{{prognaw|PHP|[[../Savant/]]|[[../PHPTAL/]]}}
{{podświetl|php}}
 
== Open Power Template ==
Zapoznamy się teraz z polskim systemem szablonów ''Open Power Template'' reprezentującym nieco inne podejście do pracy z szablonami, niż Smarty oraz napisanym specjalnie dla PHP5.
 
Omówiony w poprzednim rozdziale Savant to doskonały przykład biblioteki wykorzystującej PHP jako język szablonów. W Open Power Template sytuacja odwraca się o 180 stopni. Ten system udostępnia swój własny, XML-owy język, którego cechą szczególną jest deklaratywne podejście do tworzenia szablonów. Zamiast skupiać się na szczegółach implementacyjnych, twórca szablonu powinien jedynie powiedzieć, co chce osiągnąć i zlecić kompilatorowi wygenerowanie odpowiedniego kodu, który spełni jego życzenia. Pomaga w tym rozumienie struktury HTML szablonu oraz unikalna cecha, tzw. ''formaty danych''. Aby nie być gołosłownym, zaprezentujemy poniżej przykładowy szablon:
=== Instalacja ===
Najnowszą wersję można ściągnąć ze strony projektu: [http://opt.openpb.net] w postaci spakowanego archiwum. Zawiera ono kilka katalogów:
* ''/configurator'' - narzędzie do konfigurowania OPT (tylko w wersji 1.0.x)
* ''/docs'' - angielska dokumentacja w formacie PDF (tylko w wersji 1.0.x)
* ''/examples'' - przykładowe skrypty demonstrujące różne możliwości OPT
* ''/lib'' - źródła biblioteki. Ten katalog interesuje nas najbardziej i to jego zawartość należy dołączać do naszych projektów korzystających z OPT.
* ''/toolset'' - pakiet narzędziowy do OPT od wersji 1.1.x
* ''/unitTest'' - zestaw testów sprawdzających poprawność działania kompilatora oraz całej biblioteki. Aby go uruchomić, wymagany jest skrypt PHPUnit 1.3
 
Instalacja OPT jest bardzo prosta. Kopiujemy zawartość katalogu ''/lib'' do drzewa katalogowego naszego projektu. W kodzie naszych skryptów musimy ustawić stałą '''OPT_DIR''' pokazującą położenie plików biblioteki, a następnie dołączyć plik ''opt.class.php''. Ścieżka podana w stałej powinna być zakończona ukośnikiem.
 
<nowiki><?php
define('OPT_DIR', '../includes/opt/');
require(OPT_DIR.'opt.class.php');
?></nowiki>
 
{{Uwaga|Nie zaleca się ustawiania '''bezwzględnej''' ścieżki do katalogu w stałej ''OPT_DIR'' z powodów wydajnościowych! PHP przeszukuje wtedy niepotrzebnie kilka własnych folderów zdefiniowanych w dyrektywie ''include_path'', co niepotrzebnie marnuje czas skryptu. Ścieżka '''względna''' rozpoczyna się zawsze od '''../''' (katalog nadrzędny) lub '''./''' (katalog obecny).}}
 
Musimy także stworzyć katalogi, w których będziemy przechowywać szablony:
* ''/templates'' - pliki źródłowe
* ''/templates_c'' - katalog na użytek OPT, w którym będzie on umieszczać sobie skompilowane wersje. PHP musi posiadać prawa zapisu w tym katalogu.
 
Jeżeli zamierzamy w obrębie folderu ''/templates'' tworzyć podkatalogi, musimy także stworzyć je w ''/templates_c''.
 
=== Pierwszy skrypt ===
Zanim rozpoczniemy, konieczne będzie pewne wyjaśnienie. OPT używa nieco innej terminologii, niż Smarty. To, co w poprzednim systemie zwaliśmy zmienną szablonową, tutaj będzie blokiem (zmienne też istnieją, lecz rozpoczynają się znakiem małpy i są tworzone przez szablon, a nie przez programistę). Podobnych różnic jest nieco więcej i będziemy je stopniowo wyjaśniać.
 
Napiszemy teraz pierwszy skrypt korzystający z OPT do przetwarzania szablonów:
 
<nowiki><?php
define('OPT_DIR', '../lib/'); // 1
require(OPT_DIR.'opt.class.php'); // 2
try
{
$tpl = new optClass; // 3
 
$tpl -> root = './templates/'; // 4
$tpl -> compile = './templates_c/';
$tpl -> gzipCompression = 1;
 
$tpl -> httpHeaders(OPT_HTML); // 5
$tpl -> assign('current_date', date('d.m.Y')); // 6
$tpl -> parse('szablon1.tpl'); // 7
}
catch(optException $exception) // 8
{
optErrorHandler($exception);
}
?></nowiki>
Jak widać, skrypt startowy jest znacznie bardziej rozbudowany, aniżeli ten ze Smarty'ego. Wynika to ze specyfiki nowego systemu. Oto opis działania:
# Ustawiamy stałą ''OPT_DIR'' ze ścieżką do plików biblioteki.
# Ładujemy główny plik biblioteki.
# Tworzymy obiekt klasy ''optClass''.
# Tutaj konfigurujemy OPT. Podobnie, jak w Smarty, może to się odbywać poprzez bezpośrednie ustawianie odpowiednich dyrektyw. ''root'' zawiera ścieżkę do katalogu ze źródłami szablonów, natomiast ''compile'' - ścieżkę do katalogu dla skompilowanych wersji. ''gzipCompression'' włącza automatyczną kompresję generowanego kodu HTML, o ile przeglądarka takową obsługuje. Pozwala to przyspieszyć ładowanie strony, jednak na serwerze musi być zainstalowane rozszerzenie ''zlib''.
# OPT posiada także prosty menedżer nagłówków HTTP. W tym przypadku ustawiamy, że generujemy dokument HTML (nagłówek ''text/html''). Do dyspozycji mamy również stałe ''OPT_XHTML'' - informacja o wysyłaniu dokumentu XHTML, o ile przeglądarka obsługuje odpowiedni nagłówek oraz o ile użytkownik ustawił sobie odpowiedni priorytet. W przeciwnym razie wysyłany jest nagłówek ''text/html''. ''OPT_FORCE_XHTML'' zawsze wymusza wysłanie nagłówków XHTML-a, o ile tylko przeglądarka je rozpoznaje.
# Analogicznie, jak w Smarty, przypisujemy dane do bloków metodą ''assign()''.
# Wysyłamy żądanie parsowania szablonu ''szablon1.tpl''. Wygenerowany kod zostanie automatycznie wysłany do przeglądarki.
# W OPT wszystkie błędy obsługiwane są przez mechanizm wyjątków, które musimy przechwycić. Możemy sami napisać sobie ich obsługę, lub skorzystać z gotowej, zawartej w funkcji ''optErrorHandler()''.
 
 
Nasz szablon (''szablon1.tpl'') wygląda następująco:
 
<nowiki><html>
<head>
<title>Mój pierwszy skrypt w OPT</title>
</head>
<body>
<p>Hello world! Dzisiaj jest {$current_date}!</p>
</body>
</html></nowiki>
 
Zauważ, że w OPT bloki osadzamy identycznie, jak w Smarty, domyślnie otaczając je nawiasami klamrowymi oraz poprzedzając nazwę znakiem dolara. Po wykonaniu skryptu ujrzymy w przeglądarce stronę zatytułowaną "Mój pierwszy skrypt w OPT" oraz posiadającą zawartość, np.:
<span>
<nowiki>Hello world! Dzisiaj jest 28.12.2006!</nowiki></span>
 
Zwykłe osadzanie bloków to nie jedyna operacja, jaką można przeprowadzić wewnątrz nawiasów klamrowych. Ponieważ OPT mimo wszystko z tradycją programistyczną nie zrywa, faktycznie można umieszczać w nich niemal dowolny rodzaj wyrażeń. Poniżej zaprezentujemy skrypt, który będzie wyświetlał statystyki odwiedzin pewnego serwisu. Dla uproszczenia pominiemy na razie wszystkie rzeczy związane z bazą danych i ilości użytkowników wpiszemy do skryptu "na sztywno".
 
<nowiki><?php
define('OPT_DIR', '../lib/'); // 1
require(OPT_DIR.'opt.class.php'); // 2
 
function getActiveUsers()
{
// funkcja zwraca liczbe aktywnych uzytkownikow
return 367;
}
 
function getInactiveUsers()
{
// funkcja zwraca liczbe nieaktywnych uzytkownikow
return 62;
}
 
try
{
$tpl = new optClass;
 
$tpl -> root = './templates/';
$tpl -> compile = './templates_c/';
$tpl -> gzipCompression = 1;
 
$tpl -> httpHeaders(OPT_HTML);
$tpl -> assign('active_users', getActiveUsers());
$tpl -> assign('inactive_users', getInactiveUsers());
$tpl -> parse('statystyka.tpl');
}
catch(optException $exception)
{
optErrorHandler($exception);
}
?></nowiki>
W skrypcie definiujemy dwa bloki: ''active_users'' oraz ''inactive_users'', zatem te informacje może wyświetlić szablon. Załóżmy teraz, że szef chce widzieć także łączną liczbę użytkowników, ponieważ ma trudności z (szybkim) sumowaniem liczb większych, niż 10. Niektóre aplikacje mogą być tak złożone, że odnalezienie tych dwóch linijek w setkach kilobajtów kodu może być ciężkie - w końcu najpierw trzeba poprawić szablon, a potem zmodyfikować skrypt, by przesyłał także i trzeci blok. Jeśli zadania są podzielone między webmastera i programistę, trzeba nawet zaangażować cały zespół do poszukiwań. Jednak jak wspomnieliśmy, wykorzystamy tutaj coś więcej, niż tylko zwykłe osadzanie bloków, po prostu wykonując niezbędne sumowanie po stronie szablonu (dodajmy, że podobną rzecz można zrealizować też w Smarty):
 
<nowiki><html>
<head>
<title>Statystyki serwisu: użytkownicy</title>
</head>
<body>
<p>Aktywnych użytkowników: {$active_users}</p>
<p>Nieaktywnych użytkowników: {$inactive_users}</p>
<p>Łącznie użytkowników: {$active_users + $inactive_users}</p>
</body>
</html></nowiki>
 
Po wykonaniu skryptu otrzymamy następujący rezultat:
<span>
<nowiki>Aktywnych użytkowników: 367
Nieaktywnych użytkowników: 62
Łącznie użytkowników: 429</nowiki></span>
 
Choć OPT także przenosi do szablonów cały język programowania, należy traktować to jednak z dystansem jako pewien dodatek, kiedy inne możliwości zawodzą. W rzeczywistości przy pracach nad rozmaitymi serwisami wykorzystuje się jedynie część potencjału biblioteki, zostawiając całą logikę i przetwarzanie danych skryptom, a w szablonie umieszczając to, co szablon powinien zawierać, czyli opis, jak osadzić wygenerowane dane w kodzie HTML.
 
OPT pozwala na proste osadzenie wewnątrz szablonów list, a od wersji 1.1.0 także hierarchicznych struktur (drzew) oraz wstawek systemu dzielenia wyników na strony. Ponadto, jeśli tworzymy aplikację z wielojęzycznym interfejsem, możemy ją łatwo zintegrować z OPT, dzięki czemu nie będzie konieczne ręczne przenoszenie wszystkich komunikatów językowych ze skryptu do szablonów.
 
'''Ćwiczenie 1:''' Napisz skrypt, który najpierw wyświetla formularz, w którym pyta się o imię, nazwisko, stanowisko oraz adres e-mail osoby odwiedzającej, a po jego wysłaniu wyświetla wpisane dane w postaci ładnej wizytówki. Do wyświetlania kodu HTML użyj wyłącznie systemu szablonów Open Power Template.
 
'''Ćwiczenie 2:''' Rozszerz skrypt wizytówki o sprawdzanie poprawności wpisanych danych. Jeżeli są błędne, wyświetl odpowiedni komunikat.
 
'''Ćwiczenie 3:''' Usprawnij system raportowania błędów w skrypcie wizytówek. Jeżeli użytkownik źle wypełnił formularz, powinien zostać on przeładowany wraz z wpisaną przez niego zawartością oraz odpowiednimi komunikatami wyświetlonymi pod błędnie wypełnionymi polami.
 
{{Porada|W ćwiczeniach wykorzystaj fakt, że możesz bez żadnych konsekwencji tworzyć w szablonach bloki, którym nie przypisujesz w skrypcie żadnej wartości.}}
 
=== Tworzenie list ===
OPT również posiada znacznik określany mianem sekcji i również używa się go do tworzenia wszelkiego rodzaju list, lecz w tym systemie szablonów jego użycie wymaga znacznie mniej pracy. Spróbujmy napisać tutaj jeszcze raz skrypt do wyświetlania listy newsów z poprzedniego rozdziału, aby się o tym przekonać. Rozpoczniemy od kodu PHP, który generalnie nie ulega żadnym modyfikacjom - tu także musimy wygenerować identyczną tablicę z danymi i przekazać ją do parsera w identyczny sposób z użyciem metody ''assign()''.
 
<pre><?php
define('OPT_DIR', '../lib/');
require(OPT_DIR.'opt.class.php');
try
{
$tpl = new optClass;
 
$tpl -> root = './templates/';
$tpl -> compile = './templates_c/';
$tpl -> gzipCompression = 1;
 
$tpl -> httpHeaders(OPT_HTML);
 
$newsy = array();
 
for($i = 0; $i < 5; $i++)
{
$newsy[] = array(
'tytul' => 'Tytuł wiadomości',
'data' => date('d.m.Y'),
'tresc' => 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Cras nec diam. In hac habitasse platea dictumst. Donec id leo. Ut
feugiat augue at metus. In hac habitasse platea dictumst. Donec
pulvinar sollicitudin tellus. Quisque mattis faucibus nulla. Praesent
in mauris. Maecenas erat nisi, laoreet in, porta nec, varius ut, turpis.
Suspendisse pretium nibh at tellus placerat venenatis. Vestibulum
ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia
Curae; Etiam felis arcu, ringilla a, commodo quis, blandit id, est.
Fusce nec sapien nec libero dignissim volutpat.'
);
}
 
$tpl -> assign('newsy', $newsy);
$tpl -> parse('szablon3.tpl');
}
catch(optException $exception)
{
optErrorHandler($exception);
}
?></pre>
 
A tak będzie prezentować się szablon HTML pozwalający tę właśnie listę wyświetlić:
 
<source lang="xml" line><?xml version="1.0" ?>
<pre><html>
<opt:root>
<opt:prolog />
<opt:dtd template="html5" />
<html>
<head>
<title>OPT News!{$pageTitle}</title>
</head>
<body>
<p>Polecamy nasze produkty:</p>
{section=newsy}
<ul>
<h3>{$newsy.tytul}</h3>
<li opt:section name="products"><a parse:href="$products.url">{$products.name}</a></li>
<p>Dnia {$newsy.data}</p>
</ul>
<p>{$newsy.tresc}</p>
{/section}
</body>
</html></pre>
</opt:root>
</source>
 
Oprócz tego, Open Power Template udostępnia obiektowy interfejs programistyczny dla PHP 5.2/5.3 dostosowany do potrzeb integracji z popularnymi frameworkami, które niebawem poznamy. Do naszej dyspozycji są trzy najważniejsze elementy interfejsu:
OPT nie wymaga podawania żadnych iteratorów itd. - to, jak dokładnie wszystko jest obsługiwane od strony technicznej, jest już wewnętrzną sprawą biblioteki. Naszym zadaniem jest jedynie określenie nazwy sekcji równoznacznej w tym wypadku z nazwą bloku, w którym mieści się tablica z danymi. Do poszczególnych bloków sekcji odwołujemy się, podając najpierw nazwę samej sekcji, a później po kropce nazwę informacji, którą chcemy w danym miejscu wyświetlić.
 
# '''Opt_Class''' - główna klasa zarządzająca konfiguracją.
Analogicznie sprawa ma się z zagnieżdżaniem sekcji. Tutaj również przepiszemy na OPT skrypt obsługi biblioteki z poprzedniego rozdziału. O dziwo, także i teraz generowanie tablic z danymi odbywa się dokładnie tak samo.
# '''Opt_View''' - klasa reprezentująca tzw. ''widok'', czyli określony szablon i towarzyszące mu dane ze skryptu:
# '''Opt_Output_Interface''' - interfejs systemu wyjścia, który mówi, gdzie wysłać wygenerowany kod.
 
Podobnie jak w naszym prostym systemie edukacyjnym, nasza aplikacja WWW tworzy sobie odpowiednią liczbą widoków i przekazuje do nich dane. Jednak zamiast wykonywać je od razu, przekazuje je do jednego z systemów wyjścia, który zajmuje się wykonaniem szablonu i wysłaniem wyniku w określone miejsce. Przykładowo, jeśli skorzystamy z systemu wyjścia '''Opt_Output_Http''', dane polecą do przeglądarki, a oprócz tego możemy też stworzyć sobie system wyjścia '''Email''', który podany szablon potraktuje jako np. treść wiadomości e-mail, którą trzeba wysłać pod określony adres.
<pre><?php
define('OPT_DIR', '../lib/');
require(OPT_DIR.'opt.class.php');
try
{
$tpl = new optClass;
 
=== Instalacja ===
$tpl -> root = './templates/';
$tpl -> compile = './templates_c/';
$tpl -> gzipCompression = 1;
$tpl -> xmlsyntaxMode = 1;
 
Bibliotekę można pobrać ze strony [http://www.invenzzia.org www.invenzzia.org] - pobieramy najnowsze wydanie z gałęzi 2.0.x, które jest omówione w tym podręczniku. W ściągniętym archiwum znajdziemy katalog <code>/lib</code> z właściwym kodem źródłowym biblioteki. Pozostałe katalogi to przykłady, dokumentacja oraz testy. Przenosimy wspomniany katalog gdzieś do drzewa katalogowego naszej aplikacji WWW.
$tpl -> httpHeaders(OPT_HTML);
 
Druga czynność to stworzenie folderów na szablony. Pierwszy z nich nazwijmy <code>/templates</code> - będą tam źródłowe wersje szablonów. W drugim, <code>/templates_c</code> Open Power Template będzie zapisywać skompilowane wersje, dlatego upewnijmy się, że PHP posiada do niego prawa zapisu.
$pdo = new PDO('mysql:host=localhost;dbname=podrecznik_php', 'root', 'root');
 
Open Power Template jest częścią większej rodziny bibliotek ''Open Power Libs'', dla których potrzeb opracowane zostało wspólne mikrojądro oferujące m.in. automatyczną ładowarkę czy system obsługi błędów. Znajdziemy je w katalogu <code>/lib/Opl</code>, podczas gdy właściwy kod systemu szablonów będzie w <code>/lib/Opt</code>. Gdybyśmy chcieli użyć w przyszłości innych bibliotek z tej rodziny, wystarczy wgrać je tuż obok, gdyż będą one korzystać z tego samego jądra.
$kategorie = array();
$ksiazki = array();
 
Kolejna rzecz to ustawienie automatycznej ładowarki:
$stmt = $pdo -> query('SELECT id, nazwa, il_ksiazek FROM kategorie ORDER BY nazwa');
while($row = $stmt -> fetch())
{
$kategorie[] = $row;
}
$stmt -> closeCursor();
unset($stmt);
 
<source lang="php" line><?php
$stmt = $pdo -> query('SELECT x.id, x.nazwa, k.id AS `kategoria_id` FROM ksiazki x, kategorie k
require('/sciezka/do/opl/Opl/Base.php');
WHERE k.id = x.kategoria_id ORDER BY k.nazwa, x.nazwa');
Opl_Loader::setDirectory('/sciezka/do/opl/');
$i = -1;
Opl_Loader::register();
$kid = 0;
</source>
while($row = $stmt -> fetch())
{
if($row['kategoria_id'] != $kid)
{
$i++;
$kid = $row['kategoria_id'];
}
 
Autoloader OPL ma charakter uniwersalny, tzn. można go także wykorzystać do ładowania innych bibliotek z kompatybilnym schematem nazewnictwa (np. ''Doctrine''), aczkolwiek powyższy sposób jest dobry jedynie dla bibliotek OPL. Poniżej jest przedstawione bardziej uniwersalne podejście:
$ksiazki[$i][] = $row;
}
$stmt -> closeCursor();
 
<source lang="php" line><?php
$tpl -> assign('kategorie', $kategorie);
require('/sciezka/do/bibliotek/Opl/Base.php');
$tpl -> assign('ksiazki', $ksiazki);
Opl_Loader::addLibrary('Opl', array('basePath' => '/sciezka/do/bibliotek/'));
$tpl -> parse('szablon4.tpl');
Opl_Loader::addLibrary('Opt', array('basePath' => '/sciezka/do/bibliotek/'));
}
Opl_Loader::addLibrary('InnaBiblioteka', array('basePath' => '/sciezka/do/bibliotek/', 'handler' => null));
catch(optException $exception)
Opl_Loader::register();
{
</source>
optErrorHandler($exception);
}
?></pre>
 
Szablon:
 
<pre><html>
<head>
<title>Biblioteka</title>
</head>
<body>
<ul>
<opt:section name="kategorie"> {* 1 *}
<li>{$kategorie.nazwa} <opt:show name="ksiazki"><ul> {* 2 *}
<opt:section> {* 3 *}
<li>{$ksiazki.nazwa}</li> {* 4 *}
</opt:section>
</ul></opt:show>
</li>
</opt:section>
</ul>
</body>
</html></pre>
 
Opcja ''handler'' ustawiona na '''null''' pozwala wyłączyć dodatkowe opcje ładowania klas specyficzne dla OPL-a, które mogą nie znaleźć zastosowania przy innych bibliotekach. I to wszystko. Jeśli poustawialiśmy dobrze ścieżki, możemy już zacząć korzystać z OPT.
Chwila, a cóż to się porobiło ze składnią? Nic - to jest dalej jeden i ten sam OPT. Rzuć na chwilę okiem na skrypt PHP, gdzie podczas konfigurowania pojawiła się dyrektywa ''xmlsyntaxMode''. Dzięki niej włączamy tzw. ''tryb kompatybilności z XML'', który udostępnia alternatywną składnię znaczników, stojącą w zgodzie z językiem XML. Naturalnie OPT nie sprawdza tak ściśle, czy użycie poszczególnych wzorców pasuje do reguł języka XML i nie ma żadnego problemu, aby rozpocząć sekcję znacznikiem XML-owym, a skończyć tradycyjnym, ograniczonym nawiasami klamrowymi. Dodajmy, że styl parametrów ''nazwa="wartość"'' dostępny jest zawsze i można go używać zamiennie z listami parametrów rozpoczynających się od znaku równości.
 
=== Pierwszy szablon ===
Przejdźmy teraz do samego szablonu:
# Tutaj rozpoczynamy sekcję kategorii.
# Instrukcja '''show''' jest rozwinięciem sekcji i tu też podajemy jej nazwę. Sprawdza ona, czy do sekcji przypisane są jakieś elementy, co pozwala na niewyświetlenie znaczników &lt;ul&gt; i &lt;/ul&gt;, kiedy nie są one z racji braku takowych potrzebne.
# Nazwa sekcji została już podana w instrukcji '''show''' i tu już nie trzeba jej podawać.
# Oto odwołanie się do bloków wchodzących w skład opisu pojedynczej książki. Podajemy nazwę interesującej nas sekcji, a później blok wewnątrz niej. Alternatywnie moglibyśmy napisać ''$kategorie.ksiazki.nazwa'', ale dla OPT nie robi to absolutnie żadnej różnicy.
 
=== Sekcje ===
Zwróćmy uwagę na fakt, że OPT z góry "wie", jakie są zależności pomiędzy danymi, dzięki czemu w tym systemie szablonów nie trzeba martwić się o iteratory. Znacznie poprawia to przenośność kodu. Fragment szablonu wyświetlający listę książek można wyciąć i przenieść w inne miejsce, używając go np. do wyświetlenia wszystkich książek, bez podziału na kategorie, a nie wymagałoby to absolutnie żadnych zmian. Powstaje jednak pytanie, czy w ten sposób nie ograniczamy naszych możliwości? W końcu teoretycznie ręczne określanie wszystkich parametrów pozostawia w naszych rękach większą kontrolę. Odpowiedź brzmi: nie. Dłuższa praktyka pokazuje, że paradoksalnie nasze możliwości w ten sposób rosną. OPT zezwala na przekazywanie danych do sekcji na cztery różne sposoby (część z nich jest dostępna po włączeniu odpowiednich dyrektyw konfiguracyjnych). Dzięki wprowadzeniu takiej separacji, kod tej samej sekcji bez żadnych zmian może w jednym miejscu pracować w oparciu o jeden format danych, a w innym o drugi. Biblioteka sama zajmuje się technicznymi aspektami ich obsługi.
 
=== RenderingSzkielet drzewaplikacji ===
 
=== Zarządzanie kodem HTML ===
 
=== Interfejs wielojęzycznySnippety ===
 
=== Komponenty ===
 
=== Zakończenie ===
Na OPT kończymy poznawanie możliwości oferowanych przez systemy szablonów. W następnym rozdziale zatytułowanym [[PHP/Sztuczki]] dowiemy się, jak korzystać z systemów szablonów do osiągania różnych rezultatów. Podamy tam konkretne wskazówki, jak za pomocą szablonów tworzyć dynamiczne formularze oraz jak składać design strony z kilku szablonów. W studium przypadku przerobimy napisany wcześniej system newsów z wykorzystaniem obu poznanych systemów szablonów.