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

Usunięta treść Dodana treść
Zyx (dyskusja | edycje)
rozpoczęcie prac nad przebudową i gruntowną aktualizacją
Zyx (dyskusja | edycje)
dalsze prace nad rozdziałem
Linia 16:
<p>Polecamy nasze produkty:</p>
<ul>
<li opt:section name="products"><a parse:href="$products.url">{$products.name}</a></li>
</ul>
</body>
Linia 60:
 
=== Pierwszy szablon ===
 
Przypomnijmy sobie jeszcze raz szablon z początku rozdziału:
 
<source lang="xml" line><?xml version="1.0" ?>
<opt:root>
<opt:prolog />
<opt:dtd template="html5" />
<html>
<head>
<title>{$pageTitle}</title>
</head>
<body>
<p>Polecamy nasze produkty:</p>
<ul>
<li opt:section="products"><a parse:href="$products.url">{$products.name}</a></li>
</ul>
</body>
</html>
</opt:root>
</source>
 
Możemy tu zauważyć kilka charakterystycznych dla OPT zachowań. Szablon jest domyślnie traktowany jak dokument XML, dlatego powinien posiadać prolog <code>&lt;?xml version="1.0" ?&gt;</code>, a co więcej - jest on podany wyłącznie do wiadomości parsera. Jeśli chcemy wygenerować prolog w kodzie wyjściowym, korzystamy z instrukcji <code>opt:prolog</code>, która podana bez argumentów nadaje im domyślne wartości. Oprócz tego chcielibyśmy dodać odpowiedni DTD. Komendy DTD także idą na cele parsera biblioteki, stąd też bierze się instrukcja <code>opt:dtd</code>. Ma ona predefiniowanych kilka szablonów DTD dla najpopularniejszych języków, np. ''html5'', dzięki czemu ich wstawianie jest łatwiejsze.
 
XML wymaga od nas jeszcze jednej ważnej rzeczy, mianowicie w dokumencie nie może być więcej niż jednego głównego znacznika. W tradycyjnym HTML-u rolę głównego znacznika pełnił element <code>&lt;html&gt;</code>, ale ponieważ mamy obok niego jeszcze dwa inne, OPT oddaje nam do dyspozycji <code>opt:root</code>. Oprócz bycia głównym znacznikiem, można w nim poustawiać kilka rzeczy odnoszących się do całego szablonu.
 
Jak widać, przejście na język XML-owy w momencie, gdy XHTML oraz HTML same albo wywodzą się, albo są podobne do niego, spowodowało konieczność specjalnego traktowania niektórych elementów, jednak w praktyce musimy je wykonać tylko raz, na samym początku. Gdy zaczniemy pracować z właściwą treścią, sytuacja znacząco się odwraca. Zerknijmy na linijkę 7. Pokazane jest tam, jak osadzać zmienne ze skryptu w tekście międzyznacznikowym. Używamy do tego klamerek, w którym zapisujemy nasze wyrażenie. Zapis ten oznacza, że tytuł strony zostanie załadowany ze zmiennej <code>$pageTitle</code>.
 
W linijce 12 pragniemy wyświetlić kilka produktów jako listę wypunktowaną. Do wyświetlania list służą tzw. ''sekcje'', czyli rodzaj inteligentnych pętli. Jednak zamiast obudowywać element <code>&lt;li&gt;</code> pętlą, wystarczy że dokleimy do niego atrybut <code>opt:section</code> z podaną nazwą sekcji. Jest to prosty sposób powiedzenia: ten kawałek ma być użyty jako wzorzec do wyświetlenia pojedynczego elementu listy, przy czym nie obchodzi mnie teraz, jak ta lista będzie dokładnie działać. Nazwa sekcji umożliwia nam później dostęp do zmiennych elementu listy, np. <code>{$products.name}</code> - zauważmy, że do separacji służy nam kropka.
 
W tej samej linijce widać też, że aby wczytać zawartość atrybutu ze zmiennej, nie używamy klamerek, lecz do nazwy doklejamy <code>parse:</code>, a wyrażenie zapisujemy bezpośrednio w cudzysłowach. Plik zapisujemy do katalogu <code>./templates/</code>.
 
A oto i kod PHP, który powyższy szablon uruchomi:
 
<source lang="php" line><?php
require('/sciezka/do/bibliotek/Opl/Base.php');
Opl_Loader::addLibrary('Opl', array('basePath' => '/sciezka/do/bibliotek/'));
Opl_Loader::addLibrary('Opt', array('basePath' => '/sciezka/do/bibliotek/'));
Opl_Loader::register();
 
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
 
try
{
// Konfiguracja OPT
$tpl = new Opt_Class;
$tpl->sourceDir = './templates/';
$tpl->compileDir = './templates_c/';
$tpl->stripWhitespaces = false;
$tpl->setup();
 
// Tworzymy widok
$view = new Opt_View('szablon.tpl');
$view->pageTitle = 'Tytuł strony';
 
$list = array();
$stmt = $pdo->query('SELECT * FROM produkty');
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$list[] = array(
'name' => $row['nazwa'],
'url' => 'produkt.php?id='.$row['id']
);
}
$stmt->closeCursor();
$view->products = $list;
 
// Renderujemy
$output = new Opt_Output_Http;
$output->setContentType(Opt_Output_Http::HTML, 'utf-8');
$output->render($view);
}
catch(Opt_Exception $exception)
{
$handler = new Opt_ErrorHandler;
$handler->display($exception);
}
</source>
 
Do raportowania błędów Open Power Template używa mechanizmu wyjątków, dlatego cały kod zawarty jest w bloku '''try...catch'''. Błędów nie musimy wyświetlać samodzielnie - do dyspozycji jest specjalna klasa '''Opt_ErrorHandler''', która dodatkowo potrafi podawać różne informacje o błędzie, dzięki czemu łatwiej jest usunąć przyczynę. Sam skrypt składa się z trzech części. W pierwszej musimy skonfigurować bibliotekę, tworząc obiekt '''Opt_Class''' i ustawiając niektóre właściwości:
 
# <code>sourceDir</code> - katalog z szablonami źródłowymi (tj. <code>./templates/</code>)
# <code>compileDir</code> - katalog ze skompilowanymi szablonami (tj. <code>./templates_c/</code>)
# <code>stripWhitespaces</code> - czy usuwać ze źródeł niepotrzebne białe znaki, utrudniając analizę kodu wynikowego. Wartość '''false''' wyłącza usuwanie.
 
Po skonfigurowaniu wywołujemy metodę <code>setup()</code> i możemy zabrać się za tworzenie widoków. Obsługuje się je podobnie, jak w naszym edukacyjnym systemie z tą różnicą, że nie używamy tutaj metody fabrycznej, lecz samodzielnie tworzymy cały obiekt. W argumencie konstruktora podajemy nazwę szablonu, a później możemy do widoku przypisywać różne dane przy pomocy getterów i setterów. Przy okazji spójrzmy na linijki 23 do 33, gdzie wypełniana jest lista produktów dla sekcji. Lista jest zwykłą tablicą z elementami numerowanymi od zera, a każdy element jest tablicą asocjacyjną zawierającą kilka zmiennych.
 
Na samym końcu musimy szablon wykonać. W tym celu potrzebny jest nam jakiś system wyjścia, który zdecyduje, co zrobić z wynikiem. OPT dostarcza domyślnie dwóch takich systemów:
 
# '''Opt_Output_Return''' - zwraca kod jako wynik wykonania z powrotem do skryptu.
# '''Opt_Output_Http''' - wysyła kod do przeglądarki i udostępnia opcje zarządzania nagłówkami.
 
Skorzystamy z tego drugiego. Ma on dodatkową pomocniczą metodę <code>setContentType()</code>, która wysyła nagłówek <code>Content-type</code> z informacją dla przeglądarki, co dokładnie przysyłamy z serwera i ew. w jakim kodowaniu. Później wystarczy już tylko wywołać metodę <code>render()</code>, której podajemy za argument widok i to wszystko.
 
=== Sekcje ===