Šablonovací systém Bemplate
22.6.2012Během hledání cesty k "dokonalému webovému kódu" jsem se dostal k zastávce jménem šablonovací systém. Do této doby jsem si maximálně dělal metody Show() v daných objektech, abych je vykreslil. Z hlediska objektivního programování je to sice správně, ale trochu to nabourává MVC systém.
Každý lepší framework obsahuje nějaký šablonovací systém. Než se s ním programovat, tak jsem nejdříve vyzkoušel Smarty a pak nějaké další, ale byl jsem docela zklamaný. Asi nejlépe mi sedlo Latte, které je použito ve frameworku Nette. Hlavně se mi líbilo, že výpis proměnné je už v základu prohnán funkcí htmlspecialchars, což je nejčastější použití. Některé ostatní šablonovací systémy sice disponovaly tuto možnost nastavit, ale z nějakého důvodu pak nešlo tuto vlastnost zakázat, abych mohl vykreslit přímo HTML kód.
Nevím proč, ale ani jsem se nechtěl snažit vyextrahovat Latte z Nette a prostě jsem si naprogramoval vlastní šablonovací systém, který asi nedosahuje kvalit ostatních šablonovacích systémů, ale cca 90% běžné práce zastane a nebo lze nahradit PHPkem.
Hlavní přednosti
- je to v jednom jediném souboru 9kB velkém (většina je stejně jen komentář :-) )
- je to rychlé, protože se to cachuje a překládá do PHP souborů
- v šablonách lze použít běžný PHP kód, takže co neumí přímo bemplate, tak to můžete napsat pomocí PHP
- jednoduché na naučení, protože to obsahuje pouze 15 příkazů
- snadno implementovatelné do projektu díky depenency injection
Na to, že to vzniklo během dvou večerů, je to překvapivě účiné. Nápověda je přímo v souboru a použití poznáte z dema. Přesto zde máte výpis základních funkcí:
- {$promenna}
vypise $promennou pomoci htmlspecialchars ... misto promenne jde pouzit i funkce - {!$promenna}
vypise $promennou jako html - {; php kod }
spusti php kod - {if podminka} ... {/if}
prelozi na if (podminka) - {foreach $pole as $hodnota}
prelozi na if ($pole) foreach ($pole as $hodnota), lze pouzit i $key=>$hodnota - {first} ... {/first}
Spustí se při prvním průběhu cyklem. - {last} ... {/last}
Spustí se při posledním průběhu cyklem. - {odd} ... {/odd}
Spustí se při lichém průběhu cyklu. - {even} ... {/even}
Spustí se při sudém průběhu cyklu. - {while podminka}
prelozi na while (podminka) - {include "soubor.bpl"}
includuje sablonu a preda ji vsechny aktivni promenne - {include "soubor.bpl", array('typ' => 123,'nazev'=>'sfds')}
includuje sablonu a prida k ni parametry - {* text komentáře *}
komentář, bude odstraněn - {t $promenna}
prelozi promenou pres translate fci + htmlspecialchars ... dobre pro jazkove mutace ... funkce translate lze predefinovat - {t !$promenna}
prelozi promenou pres translate fci a vypise ako HTML - {? $promenna}
spusti debug($promenna); ... funkce debug lze predefinovat - {; phpkod() }
spusti php kod a nic nevypisuje - {define #Nazev-Bloku} ... {/define}
definice bloku - {include #Nazev-Bloku}
spusti blok a preda vsechny aktivni promenne - {include #Nazev-Bloku, array('typ' => 123,'nazev'=>'sfds')}
spusti blok a prida take dalsi promenne - ... případné další příkazy najdete přimo v souboru bemplate.php
Ukázka definice šablony
<h1>{$nazevStranky}</h1> <div>{!$htmlPopis}</div> <div class="Aktuality">
{foreach $aktuality as $item}
{include 'aktualita.bpl', array('aktualita' => $item ) }
{/foreach}</div>
Ukázka použití v PHP
require_once 'bemplate.php';
$tpl=new Bemplate();
$tpl->Set('nazevStranky','Moje aktuality');
$tpl->Set('htmlPopis','Tyhle aktuality jsou <b>super</b>');
$tpl->Set('aktuality',array(
array('nazev'=>'Nazev1',
'obsah'=>'proste nejaky html <a href="#">text</a>'
),
array('nazev'=>'Nazev2',
'obsah'=>'proste nejaky html <a href="#">text</a>'
),
array('nazev'=>'Nazev3',
'obsah'=>'proste nejaky html <a href="#">text</a>'
)
));
echo $tpl->Render('templates/index.bpl');
Komentáře
Přidej svůj komentář{t $promenna} se prelozi na echo htmlspecialchars(translate($promenna)), přičemž funkci translate si můžete určit sami v konfiguraci. Jednoduše bych to řešil tak, že bych napsal {$ [$promenna,'cz']} a v translate funkci bych si detekoval, zda to je pole a v tom případě bych věděl, že první index je text k překladu a druhý je jazyk. Ty hranatý závorky je to samé, co array(), ale je to rychlejší zápis (funguje od PHP 5.4)
Nebo můžeš klidně vlézt do kódu bemplate a udělat si vlastni podporu, protože to je fakt jednoduchý, takže za 5 minut by to umělo to, co potřebuješ.
Ale asi to rozšířím na nepovinný zápis {t $promenna,cz}, což je nejkratší zápis a je jasný, co to bude dělat.
Díky za nápad.
{t $promenna}
Nesedi me tady jedna vec, co kdyz mam vic jazyku a jak to pozna do ktereho to ma prelozit? Musi bejt key pro preklad primo v promenne nebo muzu nekam napsat jen string? Kdyz budu mit vetsi projekt tak prirazovani do promennych (a tedka kdyz budu mit nedejboze dost textu) tak zbytecne mam alokovat pamet promennyma? :-) Ja kvuli tomuto pouzivam SMARTY protoze obsahuje definice svych vlastnich bloku napr. {translate}translate this key{/translate} kde v metode ktera vola tento blok si nacitam ze sessions aktualni jazyk kde si toho prekladam. Nebo {translate lang='cs'}translate this key{/translate} Jde tohle v tvem enginu taky nejak nastavit?