Spis treści
Ta sekcja zawiera opis klas używanych w systemie. Opisane zostaną metody oraz właściwości klas.
Do elementów architektury trójwarstwowej należy zaliczyć także warstwę prezentacji. Celem klasy template jest obsługa szablonów służących do wyświetlenia danych w formie HTML/XHTML. Dzięki temu, w warstwie logiki aplikacji (skrypty PHP) nie musimy umieszczać kodu PHP - cały projekt jest dzięki temu łatwiejszy w konserwacji, a zmiana wyglądu strony jest o wiele prostsza.
Pliki szablonowe umieszczone są w katalogu /templates/{nazwa skórki}, projektu, gdzie {nazwa skórki} to katalog, w którym umieszczone są pliki z rozszerzeniem .tpl. W niniejszej sekcji postaram się przedstawić zasady projektowania szablonów oraz ich wykorzystania.
Poniżej zamieszczam kilka podstawowych reguł którymi powinni się kierować twórcy szablonów:
Ponieważ zasadę wykorzystania szablonów należałoby dobrze wyjaśnić, zaprezentuje tutaj przykład skonstruowania oraz wykorzystania prostego szablonu.
W katalogu /templates umieść folder Temp, a w nim umieść plik index.tpl o następującej treści:
<html>
<head>
<title>Przykładowa strona</title>
</head>
<body> Dzień dobry, <!--USER_NAME--> </body>
</html>
Zasada wykorzystania szablonów polega na zastąpieniu frazy zawartej pomiędzy <!-- i --> danymi pochodzącymi ze skryptu. Teraz umieść w głównym katalogu projektu, plik temp.php, który posiadać będzie następującą zawartość:
<?php
/* OBOWIAZKOWY NAGLOWEK KAZDYCH SKRYPTOW W PROJEKCIE */
DEFINE('COYOTE', true);
$root_dir = './';
include_once($root_dir . 'extension.inc');
include_once($root_dir . 'common.' . $phpEx);
/* OBOWIAZKOWY NAGLOWEK KAZDYCH SKRYPTOW W PROJEKCIE */
$template = new template('index.tpl', 'Temp');
$template->assign('USER_NAME', 'Adam Boduch');
$template->display();
?>
Aktualnie nie musisz się przejmować wierszami od 2-8. Są to standardowe instrukcje każdego pliku w projekcie Coyote. Zwróć uwagę na wiersze 10-13, które wykorzystują klasę template. W linii 10 następuje wywołanie konstruktora klasy template. W pierwszym parametrze podajemy nazwę pliku szablonowego do załadowania. Drugi parametr to nazwa skórki, która ma zostać użyta. Jednocześnie wartość tego parametru musi równać się nazwie katalogu w folderze /templates.
W wierszu 11. następuje wywołanie metody assign() której zadaniem jest zastąpienie w szablonie, wartości określonej w parametrze pierwszym (w tym wypadku USER_NAME) wartością z parametru drugiego (Adam Boduch). Metoda display() użyta w wierszu 12. spowoduje wyświetlenie skompilowanego szablonu.
Po próbie użycia skryptu temp.php, przeglądarka wyświetli zawartość poniższej strony HTML:
<html>
<head>
<title>Przykładowa strona</title>
</head>
<body> Dzień dobry, Adam Boduch</body>
</html>
Jak sam widzisz, w procesie wyświetlania szablonu doszło do kompilacji i zastąpienia danych w szablonie, tymi podanymi w skrypcie. Mam nadzieje, że teraz zaczynasz rozumieć przeznaczenie klasy template.
W poprzednim przykładzie zaprezentowaliśmy proste użycie metody assign() - zastępowanie prostych wartości. Przeanalizujmy odrobinę trudniejszy przykład - zastępowanie kilku wartości. Przypuśćmy, że plik temp.tpl posiada teraz taką zawartość:
<html>
<head>
<title>Przykładowa strona</title>
</head>
<body>
Dzień dobry, <!--USER_NAME--><br>
Dzisiaj mamy <!--NOW-->, w Lotto padły następujące liczby: <!--LOTTO-->
</body>
</html>
Mamy w tym miejscu trzy elementy, które należy zastąpić. A oto zawartość skryptu który je zastępuje;
<?php
/* OBOWIAZKOWY NAGLOWEK KAZDYCH SKRYPTOW W PROJEKCIE */
DEFINE('COYOTE', true);
$root_dir = './';
include_once($root_dir . 'extension.inc');
include_once($root_dir . 'common.' . $phpEx);
/* OBOWIAZKOWY NAGLOWEK KAZDYCH SKRYPTOW W PROJEKCIE */
$template = new template('index.tpl', 'Temp');
$template->assign(array( 'USER_NAME' => 'Adam Boduch',
'NOW' => date('d-m-Y') ) );
$lotto = array();
for ( $i = 0; $i < 6; $i++ )
{
$lotto[] = rand(1, 48);
}
$template->assign('LOTTO', $lotto);
$template->display(); ?>
W pierwszym wywołaniu metody assign() przekazana została tablica asocjacyjna. Klucze tablicy stanowią parametry do zastąpienia, a wartości to dane które mają zostać wkompilowane w szablon. W drugim wywołaniu szablonu do metody przekazana została tablica. Klasa template wyświetli elementy tablicy rozdzielone spacjami. W takim wypadku możesz również określić znak, który stanowić będzie separator elementów - np.:
$template->assign('LOTTO', $lotto, ', ');
Takie wywołanie da następujące efekty:
Dzień dobry, Adam Boduch<br> Dzisiaj mamy 14-10-2004, w
Lotto padły następujące liczby: 1, 1, 24, 2, 42, 20
Czasem przydana jest opcja kompilacji warunkowej. Chodzi tutaj o instrukcje warunkowe, które wyświetlą odpowiedni tekst jeżeli warunek został spełniony. Do tego służy metoda assign_if_block(). Oto fragment zawartości szablonu:
<body>
Dzień dobry, <!--USER_NAME--><br>
Dzisiaj mamy <!--NOW-->
<!--IF:EVEN-->
Dzień jest liczbą parzystą
<!--ELSE:EVEN-->
Dzień nie jest liczbą parzystą
<!--ENDIF:EVEN-->
</body>
Jeżeli warunek zostanie spełniony, wyświetlony zostanie blok znajdujący się po frazie <!--IF:EVEN-->. W przeciwnym wypadku wyświetlona zostanie fraza znajdująca się po <!--ELSE:EVEN-->. Oto fragment kodu wykorzystującego metodę assign_if_block():
$day = date('d');
$template->assign_if_block('EVEN', ( $day % 2 ) == 0 ? true : false );
$template->display();
Na początku, pobrany zostanie dzień miesiąca. Jeżeli liczba jest parzysta, drugi parametr metody assign_if_block() to true (warunek spełniony). W przeciwnym wypadku: false. W skutek takiego działania, wygenerowany zostanie następujący kod:
Dzień dobry, Adam Boduch<br> Dzisiaj mamy 14-10-2004 Dzień
jest liczbą parzystąRozważmy kolejny przykład - oto fragment szablonu:
<body>
Dane:
<!--BEGIN:USER_NAME-->
<li>Witaj <!--USER_NAME.NAME-->, lat <!--USER_NAME.AGE--></li>
<!--END:USER_NAME-->
</body>
Chodzi nam tutaj o wyświetlenie imienia oraz wieku danej osoby. Załóżmy jednak, że nie wiemy ile jest osób, chcielibyśmy wyświetlić w ten sposób, przykładowo 3 imiona wraz z wiekiem danych osób. Służy do tego metoda assign_block() której użycie prezentuje następujący fragment:
$data['NAME'][] = 'Marcin';
$data['NAME'][] = 'Rafał';
$data['NAME'][] = 'Kuba';
$data['AGE'][] = 24;
$data['AGE'][] = 51;
$data['AGE'][] = 15;
$template->assign_block('USER_NAME', $data);
$template->display();
Pierwszym parametrem metody assign_block() jest nazwa bloku (w tym wypadku USER_NAME). Drugi element musi być tablicą wielowymiarową. W wyniku tak zapisanego kodu, skompilowany szablon będzie wyglądał tak:
Dane:
<li>Witaj Marcin, lat 24</li>
<li>Witaj Rafał, lat 51</li>
<li>Witaj Kuba, lat 15</li>
Oczywiście powyższy przykład można zapisać także w inny sposób:
$template->assign_block('USER_NAME', array('NAME' => array('Marcin', 'Rafał', 'Kuba'),
'AGE' => array(24, 51, 15) ) );
Efekt będzie ten sam.
Często bloki, rekordy odczytywane są z bazy danych, z wykorzystaniem pętli while - np.:
while ( $row = $db->sql_fetch($result) )
{
$a_user[$i]['USER_NAME'] = $row['user_name'];
}
$template->assign_block('USERS_LIST', $a_user);
Jak widzisz, najpierw w pętli, budowana jest tablica $a_user, która po
zakończeniu pętli, przekazywana jest metodzie <method>assign_block</method>. Taki zapis można
skrócić do następującej postacii:
while ( $row = $db->sql_fetch($result) )
{
$template->assign_block('USERS_LIST', array('USER_NAME' => $row['user_name']));
}
W takim wypadku, w pętli wywołujemy metodę assign_block która także jako parametr
przyjmuje tablicę. Testy wykazały, że owa metoda jest o ok. 20% szybsza niż poprzednia.
Kolejny, bardziej zaawansowany element to instrukcje warunkowe zagnieżdżone w blokach. Oto fragment szablonu:
<body>
Dane:
<!--BEGIN:USER_NAME-->
<li>Witaj <!--USER_NAME.NAME-->
<!--IF:USER_NAME.WON-->
wygrałeś <!--USER_NAME.MONEY--> euro
<!--ELSE:USER_NAME.WON-->
niestety, nie wygrałeś nic
<!--ENDIF:USER_NAME.WON-->
</li>
<!--END:USER_NAME-->
</body>
Naszym zadaniem będzie wyświetlenie imienia oraz wylosowania liczby z zakresu 1-100. W zależności od tego czy jaka będzie wartość wylosowanej liczby, zostanie wykonana instrukcja warunkowa. Jeżeli liczba będzie większa niż 50, zostanie wyświetlona kwota wygranej. Jeżeli liczba będzie mniejsza niż 50, zostanie wyświetlony napis niestety, nie wygrałeś nic. Oto kod źródłowy:
$names = array('Marcin', 'Rafał', 'Kuba', 'Adam');
foreach ( $names as $name )
{
$data['NAME'][] = $name;
$data['MONEY'][] = $money = rand(1, 100);
$data['WON'][] = ( $money >= 50 ? true : false );
}
$template->assign_block('USER_NAME', $data);
Podany przykład, w zależności od losowania wyświetli różne rezultaty, w moim przypadku jest to np.:
<body>
Dane:
<li>Witaj Marcin niestety, nie wygrałeś nic </li>
<li>Witaj Rafał wygrałeś 51 euro </li>
<li>Witaj Kuba niestety, nie wygrałeś nic </li>
<li>Witaj Adam niestety, nie wygrałeś nic </li>
</body>
Podczas budowania interfejsów, w szablonie można użyć frazy <!--INCLUDE (nazwa pliku)--> która w tym miejscu zostanie zastąpiona przez zawartość podanego pliku. Znacznie ułatwia to tworzenie szablonu, kod nie musi być dzięki temu powielany. Możesz np. utworzyć plik bottom.tpl który zawierać będzie stopkę dokumentu:
<hr> Dziękuje za uwagę :-)
Następnie, w pliku index.tpl, w wybranym miejscu wstawić taką frazę:
<!--INCLUDE bottom.tpl--> </body> </html>
Zostanie ona zastąpiona kodem z pliku bottom.tpl.
function template($handle, $tpl_name = '')
Jest to konstruktor klasy. Pierwszym parametrem jest nazwa pliku szablonowego; drugi to nazwa skórki używanej do generowania strony.
function tpl_load(&$file_name)
Funkcja prywatna, nie powinna być używana z zewnątrz klasy. Jej zadaniem jest sprawdzenie istnienia nazwy pliku oraz sprawdzenie, czy ów plik nie jest już skompilowany, a jego kopia nie leży w cache. Jeżeli tak, ładowana jest kopia z pamięci podręcznej.
function tpl_load_file(&$file_name)
Ta funkcja odpowiada za rzeczywiste załadowanie pliku określonego w parametrze do pamięci. Również nie powinna być używana na zewnątrz klasy. Funkcja zwraca zawartość odczytanego pliku.
function tpl_include($include_name)
Funkcja używana w trakcie wykonywania skompilowanego szablonu. Jej zadaniem jest włączenie i wykonanie w odpowiednim miejscu pliku "includowanego".
function assign($key, $value = '', $separator = ' ')
Często używana funkcja służąca do zastępowania danych fraz w szablonie tymi, przekazanymi w parametrze $value tej funkcji. W rzeczywistości funkcja nie realizuje zastępowania lecz przypisuje dane do właściwości $tpl_var. Właściwości są zapisywane w takiej postaci: tpl_var['.'][0][$key] = $value; Dla użytkownika klasy nie powinno to jednak mieć znaczenia.
Ważną rzeczą jest fakt, że metoda ma wiele zastosowań, tzn. może przyjmować różnego rodzaju parametry. W najprostszym wydaniu jest to para klucz => wartość, określone parametrami $key, $value. Parametr $key może być także tablicą asocjacyjną, a parametr $value, normalną tablicą.
Trzeci, opcjonalny parametr $separator określa znak który posłuży do rozdzielenia elementów tablicy jeżeli $value jest tablicą. Przykłady wykorzystania metody assign() przedstawiono wcześniej.
function assign_block($tpl_block_name, $var_array)
Metoda służy do zastępowania w szablonie całych bloków. Pierwszym parametrem musi być nazwa bloku (np. USER_NAME, MOD_LIST itp). Drugi parametr $var_array, musi być tablicą która zawierać będzie elementy zastępujące oraz do zastąpienia. Funkcja także nie realizuje operacji zastąpienia, tylko przypisuje dane do tablicy tpl_var, w takiej postaci: tpl_var[$tpl_block_name][(numer bloku)][(klucz)] = (wartość). Nie jest to jednak istotna informacja dla użytkownika klasy.
Przykłady użycia tej metody znajdują się powyżej.
function assign_if_block($tpl_block_name, $result)
Metoda służy do wykonywania instrukcji warunkowych. Nie dokonuje bezpośrednich zmian w kodzie szablonu, lecz zapisuje informacje do właściwości block_if_else.
function compile($code)
Funkcja używana w metodzie display(), służy do kompilacji szablonu do kodu PHP. Jeżeli ciekaw jesteś rozwiązań wewnętrznych klasy, zajrzyj do kodu źródłowego pliku include/template.php. Działania dokonywane we wnętrzu tej klasy, to m.in: zamienianie danych z tablicy tpl_var, wykonanie metod: compile_include_block(), compile_tag_block(), compile_if_block(). Funkcja używana jest tylko wewnątrz klasy.
Parametr $code zawiera fragment kodu szablonu do skompilowania.
function compile_include_block(&$code)
Funkcja zastępuje instrukcje <!--INCLUDE--> w szablonie, odpowiednim kodem PHP.
function compile_tag_block(&$code)
Funkcja realizuje rzeczywiste zastąpienie fraz w szablonie na pętle PHP.
function compile_if_block(&$code)
Funkcja realizuje rzeczywiste zastąpienie fraz w szablonie na instrukcje warunkowe języka PHP.
function compile_write(&$handle)
Metoda wywoływana w poziomu funkcji tpl_load(). Parametr $handle, w tym wypadku określa nazwę pliku - np. index.tpl. Jednocześnie jest to klucz w tablicy asocjacyjnej $compiled_code która zawiera skompilowany kod pliku szablonowego. Funkcja compile_write() realizuje zapis skompilowanego pliku do pamięci podręcznej cache. Ma to na celu przyspieszenie wyświetlania szablonu przy kolejnym użyciu. Jeżeli przy kolejnym użyciu zostanie odnaleziony plik w cache, nie będzie wykonywana funkcja compile() ani compile_write(), po prostu skompilowany szablon zostanie wyświetlony.
function display($handle = '')
Najważniejsza funkcja, mimo, iż używana na końcu wykonuje metodę tpl_load() która z kolei kompiluje szablon. Następnie tak skompilowany szablon (zawarty w tablicy $compile_code) jest wykonywany przy pomocy funkcji PHP: eval().
Opcjonalny parametr $handle daje możliwość ustalenia pliku który zostanie wyświetlony (w przypadku, gdy do wyświetlenia strony branych jest kilka plików szablonowych).