Nie mam powodu dlaczego miałbym nie pokazać swojego kodu na forum - nie wstydzę się go

nie mniej, sama klasa templatek to nie wszystko, bo to jest tylko w sumie parser i domyślnie nie pobiera z jakiegoś cache przetworzonego szablonu. Podzielić na dwie klasy musiałem, żeby pierwsza klasa działała w sumie bez niczego, ponieważ wykorzystuje ją jeszcze do rendrowania szablonów stron błędów, a tak jako tako błędów być nie może, spowodowanych np przez system cache. Ale posiada ona swoje podstawowe funkcjonalności a wygląda ona tak:
https://gist.github.com/1471387 jedyne co byś musiał w niej zmienić, to 35 linijkę:
'template_dir' => array(Config
::get('path.app').DIRECTORY_SEPARATOR
.'templates'.DIRECTORY_SEPARATOR
, Config
::get('path.common').DIRECTORY_SEPARATOR
.'templates'.DIRECTORY_SEPARATOR
)
zamiast tej tablicy ścieżek, bo można podać ich kilka, ze względu takiego że u siebie wykorzystuje coś w rodzaju aplikacji, gdzie jest domyślna aplikacja "common", która też służy jako aplikacja do współdzielenia (szablonów/tłumaczeń/modułów/komponentów/modeli) między innymi aplikacjami. Wymyśliłem sobie coś takiego, ponieważ w kilku miejscach zdarzało mi się wykorzystywać mojego fw, do kilku różnych aplikacji, więc żeby utrzymać jakoś w miarę rozsądnie ten kod, zrobiłem podział na aplikacje - raczej nic odkrywczego. Więc tą linijkę 35, możesz zmienić na taką linijkę:
'template_dir' => '/path/to/templates/'
Pamiętając o umieszczeniu slasha na końcu podanej ściezki. Możesz podać tablicę ścieżek. Z racji tego że jest to tylko parser, nie ma takich bajerów jak includowanie innych templatek, czy includowanie całego komponentu (coś w rodzaju akcji w module, może to być np jakiś system komentarzy etc). Jak tego używać? Już pokazuje:
<?php
$template = new TemplateParser(); // tworzymy obiekt, możemy do konstruktora przekazać ustawienia
'title' => 'Tytuł mojej nowej strony!',
'content' => 'Lore ipsum'
)); // podajesz tablicę asocjacyjną parametrów, gdzie kluczem jest nazwa zmiennej w szablonie
$wynik = $template->render('index'); //nazwa szablonu, bez rozszerzenia (domyślne rozszerzenie .tpl)
// do zmiennej $wynik został przekazany przetworzony szablon. Możemy ten szablon wyświetlić teraz:
// możemy go też przekazać dalej, lub wyświetlić dalej, w sumie gdzie chcemy.
// U mnie przetworzony szablon jest przekazywany do klasy response, która przesyła go do przeglądarki wraz z nagłówkami.
Tak wygląda kod php, a tak wygląda szablon:
<!DOCTYPE html>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> {ignore}
body { margin: 0; padding: 0; text-align: center; background: #F2F2F2; font-family: Arial; font-size: 13px; line-height: 1.6; color: #444; }
{/ignore}
{@$content}
Przetworzony szablon wygląda tak:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>
<?php echo $title ?></title>
<style>
body { margin: 0; padding: 0; text-align: center; background: #F2F2F2; font-family: Arial; font-size: 13px; line-height: 1.6; color: #444; }
</style>
</head>
<body>
</body>
</html>
Pojedyncza małpa (@) w klamrach oznacza echo, ale można też normalnie używać echo i w sumie jakiejkolwiek składni php chcemy. Jedynie pamiętając, że jak będziemy w klamrze chcieli wykorzystać małpę, to musimy "escapować" małpę, małpą. Czyli postawić dwie mały, a wyjdzie nam jedna. Korzystanie z bloków kodu (pętle, warunki) jest takie samo jak w php, z tym że lepiej korzystać z alternatywnego zapisu tych bloków:
<!DOCTYPE html>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> {ignore}
body { margin: 0; padding: 0; text-align: center; background: #F2F2F2; font-family: Arial; font-size: 13px; line-height: 1.6; color: #444; }
{/ignore}
{if(!empty($content)):}
{@$content}
{endif}
O alternatywnym zapisie można poczytać w dokumentacji php, a na szybko wygląda to tak:
<?php
// warunek
if($warunek):
// ...
endif;
if($warunek):
// ...
elseif($warunek2):
// ...
endif;
// blok switch
switch($zmienna):
case 1:
// ...
break;
case 2:
// ...
break;
default:
// ...
break;
endswitch;
// pętla for
for($i = 0; $i < 10; $i++):
// ...
endfor;
// pętla foreach
foreach($array as $row):
// ...
endforeach;
// pętla while
while($warunek):
// ...
endwhile;
Klamry prawdę mówiąc nie są niczym innym jak tagami php: <?php ({) oraz ?> (}). Ale żeby przypadkiem nam tych klamer nie podmieniło w miejscu w którym nie chcemy, a może to być css, javascript, lub nawet sam html. Wówczas taki kawałek kodu który zawiera klamry, łapiemy blokiem ignore:
<!DOCTYPE html>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> {ignore}
body { margin: 0; padding: 0; text-align: center; background: #F2F2F2; font-family: Arial; font-size: 13px; line-height: 1.6; color: #444; }
/* ten kod css zostanie pominięty, a w przetworzonym szablonie nie będzie bloku ignore */
{/ignore}
{@$content}
Odnośnie samej klasy szablonu - nie jest to szczyt, pewnie są lepsze, pewnie kale w oczy wredny eval, no ale inaczej nie wiedziałem jak to rozwiązać. Eval jest używany tylko wtedy kiedy nie można sobie za bardzo pozwolić na uruchomienie cache i skorzystanie z cache. W przypadku kiedy cache działa - czyli kiedy aplikacja działa prawidłowo, można napisać właściwą klasę szablonu, która nadpiszę metodę rendrer klasy TemplateParser, dodają dodatkowe funkcje (includowanie innych szablonów, lub includowanie komponentów), a wyglądać to może tak:
https://gist.github.com/1471520 w ten sposób zyskujemy możliwość includowania komponentów i szablonów, oraz nasze szablony są już przetrzymywane w cache, dzięki czemu nie korzystamy z evala, a nasze szablony działają dużo szybciej, ponieważ cache szablonów, to zwykły kod php, czyli największym narzutem będzie includowanie tego szablonu. Użycie dodatkowych opcji:
{include_component('layout::header')}
<form method="post" action="{@BASE_URL}/login" name="logowanie"> <input type="text" id="id_login" name="login"><br> <input type="password" id="id_password" name="password"><br>
{include('footer')}
komponentem może być nasz cały skomplikowany top strony, możemy przekazać do niego jakieś parametry etc. W stopce możemy mieć tylko zwykły kod html, więc wystarczy że zaincludujemy szablon.
Niektóre rozwiązania podpatrzone w symfony (metoda evaluate, z nieszczęsnym evalem ;p). Jak się komuś podoba - korzystać, nie zapominając napisać do tego klasy która będzie dziedziczyła klasę parsera i nadpisywała metodę render, która nie tylko nie potrzebnie przetworzy nam szablon w evalu, ale również w przypadku kiedy stosujemy cache, to metoda ta, sama sprawdzi czy szablon który chcemy przetworzyć, czy istnieje. W przypadku kiedy mamy w miarę przyzwoity system cache, w którym możemy podać sobie "zależność" od innego pliku, wówczas ta dodatkowa funkcjonalność parsera będzie zbędnym narzutem wydajnościowym (nie wielkim, ale grosz do grosza i będzie kokosza). Stosować możecie klasę gdzie chcecie, zmieniając ją jak chcecie, jedynie zostawiając info o autorze. Ewentualnie jak ktoś będzie chciał może zarzucić jakąś krytyką.
@watas odnośnie jakichś materiałów do czytania, w sumie obiektówki nie uczyłem się jakoś specjalnie z książek, znaczy podstawy tam przeczytałem, ale nie wiele tam na temat obiektywności tak na prawdę było. Resztę doczytałem z internetu, jak w sumie sporo osób. Czytaj blogi na planeta.php.pl analizuj popularne frameworki (symfony, zend, kohana, yii itp). W sumie najwięcej się nauczyłem z analizy frameworków.
EDIT: zapomniałem o jednej jeszcze rzeczy, w smarty podobał mi się sposób zapisywania tablicy wielowymiarowej:
{$tablica.klucz.drugi_klucz.trzeci_klucz}
I w tej mojej klasie, również można tak zapisywać tablice, ale można również je zapisywać w klasyczny sposób:
{$tablica['klucz']['drugi_klucz']['trzeci_klucz']}
Praktycznie żadnych ograniczeń, prócz właściwie 2:
- kod php umieszczamy w klamrach, lub w tagach php (nie wiem czy to ograniczenie, ten kod tak czy siak musimy umieścić w tagach, więc umieszczanie w klamrach chyba nie jest ograniczeniem)
- wewnątrz klamry lub kodu php, nie możemy umieszczać klamr przykładowo bloków warunkowych, lub pętli. Stąd alternatywny zapis tych instrukcji.