Sistem templateov ?

Kako najlažje narediti sistem templateov ? Tako kot je recimo phpBB, phpLD ... itd. da lahko delajo drugi template pa jih dajo v mapo pa dela ... kako bi to najlažje naredil s php ? Mislim po kakem principu bi naj delovalo ?

Dokaj preprosta verzija bi bila da pač naredil file ki se includa pa je noter vsa oblika, spremenljivke pa v <? echo $neki; ?>, čeprav koliko sem gledal se to za template ne uporablja, večina je {neki} ... v čem je sploh razlika ? Če naredim tako ali drugače ?

Ali naj uporabim čisto tretjo stvar ? Katero ? In pa kaj imajo radi designerji templatov ?

8 odgovorov

Poglej si Smarty

Ja sem pravkar googlal, pa sem naletel na tole ... med drugim ga uporablja tudi phpLD ... drugače pa sem nekje našel tole :

In short, the point of template engines should be to separate your business logic from your presentation logic, not separate your PHP code from your HTML code.

:D

In short, the point of template engines should be to separate your business logic from your presentation logic, not separate your PHP code from your HTML code.
:D

To kar si napisal je osnovna ideja templatov. Tega se lepo drzi Savant ki med drugim ne kompajlira template v php, ker se kot jezik za template upurablja php. Lepo dela tudi v php5 z Exceptni edino za kompatibilnost E_STRICT rabis verzijo 3 nalozit.

Meni osebno je ljubsi Smarty kljub temu da ga mnogi kritizirajo zaradi kompajliranja templatov in uporabo svojega jezika ki se ga mores naucit. Glede na to da je od leta 2001 ko so ga lansirali sama zasnova ostala vec ali manj enaka jim ni za zamerit. ;) Cakamo pa verzijo ki bo metala ven php5 exceptione.
Zakaj ga ljudje se vedno radi uporabljajo: Ker obstaja malo morje pluginov (Gettext), filtrov (removeHTMLComments, RemoveWhiteSpace, Gzip), ker ima razvit svoj cache sistem, ker ga z malo truda lahko vgradis tudi v razne MVC frameworke (CodeIgniter, ZendFramework, ...)

Kar se pa tice tvojih vprasanj pa si nametal kar nekaj zadev, ceprav ne vem tocno kaj zelis vedet. Izbira template sistem je odvisna od tebe. Ce ti to ne odgovarja in imas cas lahko vedno napises svojega ;)
Kar se pa tice dizajnerjev - jaz se nisem srecal nobenega, ki bi se ukvarjal z templati ter tagi in samimi template sistemi. To pri nas vec ali manj delajo programerji ... popravite me ce se motim!

LP, AlesL

Ja, prav zato sem želel svoj sistem, ker pri smarty recimo maš svojo sintakso, itd. ... če si naredim svojega, pa nikoli nebom mel problemov, ker bom na pamet vedo kje je kaj ... čeprav zadeva ni tako preprosta ko sem na začetku mislil :).

:)
Zdi se mi potratno da bi nekdo sel izumljat toplo vodo, v tem malem morju temlate jezikov, poleg tega pa je tukaj php ki opravi svoje delo vec kot odlicno. Ce pa zares zelis blizje spoznati ta svet ti vseeno priporocam da si ogledas Smarty ... kot sem ze prej napisal obstaja malo morje zadev za njega pa tudi sam lahko hitro napises kaksno zadevico.

Navedel ti bom primer pre plugina. To je dolocena skripta, ki se izvede preden se poslje template v obdelavo Smarty parserju. Primeri takih filtrov so ce zelis npr odstraniti odvecne komentarje iz kode, popraviti slovnicne napake z Dictionarijem ... Ta primer plugina v kodi najde inline Javascript in z uporabo
JsMin classa ven pomece odvecno saro-> komentarje, presledke, vrstice ...

plugin registriramo ob inicializaciji smarty-ja:
...

$smarty = new Smarty();
$smarty->load_filter('pre', 'jsMin');

Kot vidimo (glej spodaj) je celoten inline Javasript obdan z custom Smarty tagom {jsMin}{/jsMin}. V kodi opazimo tudi tag {t}{/t} ki je bil registriran kot block funkcija ki prevede del znotraj taga (wraper je lahko razlicen: cvs, xml, Gettext) ... mogoce o tem vec kdaj drugic :) Vsi smarty tagi znotraj javascripta so obdani z dodatnima oklepajima {} ker s tem dolocimo pozneje v funkciji JsMin, katere dele kode naj smarty ne parsa. Ja sam Smarty ne prebavlja embendanega Javascripta in CSS-ja in mu je potrebno povedat eksplicitno kako pa kaj.

Poglejmo sedaj funkcijo.

/**
 * Mimize embanded JsScript
 *
 * @uses _jsMin
 * @param string $tplSource
 * @param object $smarty
 * @return string
 */
function smarty_prefilter_jsMin($tplSource, &$smarty)
{
    $regex = "/\{jsMin\}(.*?)\{\/jsMin\}/s";
    return  preg_replace_callback($regex, _jsMin, $tplSource);
}
/**
 * Does the hard work
 *
 * @param array $m
 * @return mixed
 */
function _jsMin($m) {

    $jScript = $m[1];
    //Jscript without {jsMin} is second

    $jScript = preg_replace('/{{/', '{/literal}{', $jScript);
        $jScript = preg_replace('/}}/', '}{literal}', $jScript);
        //do not interprate display as is

    /**
       * javascript packer
       */
    require_once 'jsmin.php';
    $jScript = JSMin::minify($jScript);

    $result = "{literal}<script type=\"text/javascript\">\n";
        $result .= $jScript . "\n";
        $result .= '</script>{/literal}' . "\n";

    return $result;
}

Na kratko: Z regEx dobimo ven celotno vsebino ki je med {jsMin} tagom. Ce je znotraj se kaksen smarty tag insertamo literal in dobimo {/}literal{tag}{literal}, posljemo vsebino skozi Jsmin jo obogatimo z script tagom in vrnemo nazaj smartyju :)

Template izgleda priblizno takole:
[HTML]
{jsMin}
function employerRegister(formId) {
var valid = new Validation(formId, {onSubmit:false,immediate:true,stopOnFirst:true} );
Validation.addAllThese([
['required', '{{t}* Polje mora biti izpolnjeno.{/t}}', function(v) {
return !Validation.get('IsEmpty').test(v);
}],
['validate-number', '{{t}* V to polje vpišite samo številke.{/t}}', function(v) {
return Validation.get('IsEmpty').test(v) || (!isNaN(v) && !/^\s+$/.test(v));
}],
['validate-email', '{{t}* Vpišite veljaven elektronski naslov. Primer fred@domain.com .{/t}}', function (v) {
return Validation.get('IsEmpty').test(v) || /\w{1,}[@][\w-]{1,}(.){1,3}$/.test(v)
}]
}

}
{/jsMin}
[/HTML]

Smarty dobi:
[HTML]
{literal}<script type="text/javascript">
function employerRegister(formId){var valid=new Validation(formId,{onSubmit:false,immediate:true,stopOnFirst:true});Validation.addAllThese([['required','{/literal}{t}* Polje mora biti izpolnjeno.{/t}{literal}',function(v){return!Validation.get('IsEmpty').test(v);}],['validate-number','{/literal}{t}* V to polje vpišite samo številke.{/t}{literal}',function(v){return Validation.get('IsEmpty').test(v)||(!isNaN(v)&&!/^\s+$/.test(v));}],['validate-email','{/literal}{t}* Vpišite veljaven elektronski naslov. Primer fred@domain.com .{/t}{literal}',function(v){return Validation.get('IsEmpty').test(v)||/\w{1,}[@][\w-]{1,}(.){1,3}$/.test(v)}],['validate-password','{/literal}{t}* Vaše geslo mora biti daljše od 5 znakov in ne sme biti enako vašemu E-mail naslovu.{/t}{literal}',{minLength:5,notEqualToField:'employerEmail'}],['validate-password-confirm','{/literal}{t}* Ponovljeno geslo se ne ujema z vpisanim. Ponovno vnesite vaše geslo.{/t}{literal}',{equalToField:'employerPassword'}]]);var result=valid.validate();if(result==false){$('errorDiv').style.display='block';$('errorH1').innerHTML='{/literal}{t}Registracija novega delodajalca - napaka!{/t}{literal}';}else{alert('submit');}}
</script>{/literal}
[/HTML]

HTML source v browserju pa izgleda enako le da nima {literal} tagov.

Velika vecina razvijalcev uporablja template sisteme ne zaradi tega da v php-ju nastavijo spremenljivko assign->misko = "wow super je tole" ampak da si predvsem olajsajo zadeve s tem da si postopoma pripravijo razne plugine, helperje, filtre ki jim potem z pridom uporabljajo!

LP

Mnjah, na koncu sem razmišlal da bi imel tako wordpress ...

[HTML]... <div class="neki"><? out("meni"); ?> - tralala </div> ... bla bla[/HTML] ali kaj pač ... kličeš funkcijo, pa ti lepo izpiše, če bi delal z echo bi bilo še lepše, lahko kake malenkosti kaj v template popraviš ... čeprav to ravno ni rešitev da vse zapocaš ...

Ne poznam (se) wordpressov template sistem, ampak ce lahko sklepam po ostalih so vec ali manj zasnovani enako.

To kar ti zelis ni nic drugo kot nek helper oziroma funkcija ki jo klices iz templata.

Ali imas to reseno kot tag ali ne princip je isti.

[HTML]
//z tagom
<div>{menu level="top"}</div>
//brez
<div><?php echo $this->menu(array('level' => 'top') ?></div>
[/HTML]

/**
* Generate menu
* @param array $params
* @return string
*/
public function menu($params)
{
   $level = (array_key_exists('level', $params)) ? $params['level] : 'top';
   //menu level
   $db = ....
   //database adapter
   $level = $db->quoteInto('level = ?', $level);
   $rows = $db->execute("SELECT id, title FROM menu WHERE $level");
   if ($rows) {
     $menuStr = "<ul>\n";
     foreach ($rows as $row) {
       $menuStr = "<li class=\"$level\"> ...</li>\n";
     }
     $menuStr .= '</ul>';
   }
   return $menuStr;
}

/wordpress/wp-content/themes/classic/header.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>

<head profile="http://gmpg.org/xfn/11">
    <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />

    <title><?php bloginfo('name'); ?><?php wp_title(); ?></title>

    <meta name="generator" content="WordPress <?php bloginfo('version'); ?>" /> <!-- leave this for stats please -->

    <style type="text/css" media="screen">
        @import url( <?php bloginfo('stylesheet_url'); ?> );
    </style>

    <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="<?php bloginfo('rss2_url'); ?>" />
    <link rel="alternate" type="text/xml" title="RSS .92" href="<?php bloginfo('rss_url'); ?>" />
    <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="<?php bloginfo('atom_url'); ?>" />

    <link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />
    <?php wp_get_archives('type=monthly&format=link'); ?>
    <?php //comments_popup_script(); // off by default ?>
    <?php wp_head(); ?>
</head>

<body>
<div id="rap">
<h1 id="header"><a href="<?php bloginfo('url'); ?>/"><?php bloginfo('name'); ?></a></h1>

<div id="content">
<!-- end header -->

Takole zgleda glava recimo, samo temu nevem če bi lahko reko ravno template system, ker se samo php funkcije kličejo, cel template je tako naret, ni svojih tagov, tako recimo phpBB { in } in nevem zakaj komplicirati s tem ? Kaka je razlika če pustim <? ali pa zamenjam s { ?

S par funkcijami maš to zelo hitro nareto, kličeš pa tako sem en post prej napisal.

<? out("meni"); ?>

recimo ...