Separa-ti logica de design cu Smarty Template Engine

postat acum 3 ani de Stefanescu Mihai in categorie iNoob

Smarty este un template engine ce iti permite sa iti separi designul HTML si CSS de codul PHP foarte usor. Pe langa separarea logicii de partea de design are si functii precum formatarea datelor, parcurgerea valorilor, si asa mai departe. Pe parte de cache este foarte flexibil si creste performata site-ului scazand folosirea de latime de banda (bandwidth).  Din experienta personala va pot spune ca Smarty poate micsora timpul de lucru (per proiect) cu pana la 40%, pentru ca nu mai trebuie sa scrii atat de mult cod. In acelasi timp te ajuta si la organizarea fisierelor si la mentinerea unui layout standard.

Instalarea

Acest Template Engine poate fi descarcat de aici. Instalarea este foarte simpla, de fapt consta doar in dezarhivarea in folderul in care vrei sa creezi aplicatia web si sa incluzi fisierele Smarty.class.php in fisierele tale. (SmartyBC.class.php se foloseste pentru compatibilitatea cu versiunile mai vechi)

Configurarea

Organizarea folderelor este importanta si iti va fi benefica pe termen lung.

In directorul principal (public_html sau pe localhost este htdocs sau www) creaza un folder numit private ce va contine urmatoarele patru foldere:

  • classes – aici tinem clasele, astfel facand autoincarcarea (__autoload) mai usoara
  • compiledir – aici sunt stocate fisierele compilate de smarty
  • templates – aici vom avea fisierele template-ului
  • cache – aici sunt tinute fisierele cache create de smarty

Urmatorul pas este sa mutam fisierele Smarty in directorul classes. Acum, in folderul private creaza un fisier numit config.php.

C-am asa ar trebuii sa arate pana acum:

In fisierul config.php salvam caile catre folderele importante. Astfel, daca trebuie sa redenumesti un folder nu vei fi nevoit decat sa editezi 1 fisier.

Tot in acest fisier v-om crea o functie de autoincarcare a claselor. Deci, fisierul config.php va arata asa:

<?php
    //Definire Foldere
    define('DS', DIRECTORY_SEPARATOR);
    define('DIRECTORY_TEMPLATES', 	dirname(__FILE__) . DS . 'templates' . DS);
    define('DIRECTORY_CACHE', 		dirname(__FILE__) . DS . 'cache' . DS);
    define('DIRECTORY_COMPILEDIR',	dirname(__FILE__) . DS . 'compiledir' . DS);
    define('DIRECTORY_CLASSES',		dirname(__FILE__) . DS . 'classes' . DS);
    //end

    //Functie autoincarcare
    function autoload($class_name)
    {
        if(file_exists(DIRECTORY_CLASSES . $class_name . '.class.php'))
        {
            require_once DIRECTORY_CLASSES . $class_name . '.class.php';
        }
    }
    //register function
    spl_autoload_register('autoload');	
?>

Crearea de Template-uri

In folderul templates vei avea 2 fisiere: layout.tpl si index.tpl. Template-ul layout va tine designul paginilor, iar fisierul index ca detine continutul body al paginii index.

In fisierul layout.tpl putem avea un cod de forma:

<!DOCTYPE html>
<html>
<head>
    <title>Articol Template Engine Smarty</title>
</head>
<body>
    <!-- Blocul Body -->
    {block name=body}{/block}
</body>
</html>

Iar index.tpl va arata de forma:

{block name=body}
	<h1>Tutorial Smarty</h1>
    <p>Tot ce punem in afara acestui block nu va mai fi afisat.</p>
{/block}
<p>Acest text nu va fi afisat pentru ca nu este in blocul bodu.</p>

In fisierul layout se poate observa un tag block cu numele body. Acest tag block tine locul tagului body. Orice template ce foloseste un fisier layout.tpl trebuie sa aiba un tag block cu numele body. Iar in index, tot ce nu este in tag-ul block nu este afisat.

Atribuirea valorilor in variabilele templateului

In exemplul anterior v-am aratat cum puteti afisa paginile folosind un layout si extensiile aferente, dat paginile sunt statice. Daca dorim sa schimbam continutul? Solutia gasita de Smarty sunt variabilele carora le putem da anumite valori. Deci, hai sa schimbam continutul fisierului index.tpl astfel:

{block name=body}
    <h1>{$heading}</h1>
    <p>{$paragraph}</p>
{/block}

Variabilele din fisierele tpl sunt scrise intre acolade  {} si incep cu semnul dolarului ($). Dupa cum se poate observa in exemplul de mai sus, variabilele sunt heading si paragraph. Pentru a le defini trebuie sa mergem in fisierul index.php

<?php
    //randuri ce trebuiesc inclus in fiecare fisier al scriptului
    require_once '../private/config.php';

    //Setare foldere
    $smarty = new Smarty;
    $smarty->setTemplateDir(DIRECTORY_TEMPLATES);
    $smarty->setCacheDir(DIRECTORY_CACHE);
    $smarty->setCompileDir(DIRECTORY_COMPILEDIR);
    //end

    //asignare valori pentru variabile
    $smarty->assign('heading', 'Bun venit pe pagina tutorialului Smarty!');
    $smarty->assign('paragraph', 'Felicitari, ai inceput sa inveti ceva nou azi.');
    //end

    //Afisare pagina
    $smarty->display('extends:layout.tpl|index.tpl');
?>

Pentru a atribui o valoare unei variabile trebuie sa folosim functia assign.

 Buclele (Loops)

Smarty poate procesa si array-uri prin mai multe metode. Iata doua dintre acestea:

  • foreach
  • section

Section este chiar usor de folosit, o data ce ati inteles cum functioneaza. Iata un exemplu de element de tip Select folosind Section:

{block name=body}
    <h1>{$heading}</h1>
    <p>{$paragraph}</p>
    <div>
    <select>
    	{section name=number loop=$array}
        	<option>{$array[number]}</option>
        {/section}
    </select>
    </div>
{/block}

O sectiune are nevoie de nume ce este folosit pe post de index pentru elementul curent si in acelasi timp este o bucla while ce parcurge array-ul.

O sectiune poate lucra decat cu array-uri indexate numeric, dar pot fi suprapuse cat de multe doriti. Acum trebuie sa modificati si fisierul index.php, adaugand o linie de cod ce contine celelalte atribuiri.

$smarty->assign('array', range(1, 20));

Mereu trebuie sa faci o atribuire inainte de a afisa un template. Acum, ruleaza fisierul index.php si vei observa rezultatele modificarii.Foreach este o versiune de section mai puternica. Poate sa primeasca atat array-uri numerice cat si array-uri asociative. Din experienta proprie va pot asigura ca functioneaza perfect si cu array-uri multidimensionale asociative precum mysqli_result::fetch_all si PDOStatement->fetchAll.Hai sa cream un array multidimensional si sa il atribuim unei variabile numita result.

$result = array(
	0 => array(
		'id' => 222,
		'name' => 'codeprada'
	),
	1 => array(
		'id' => 333,
		'name' => 'Jessica'
	),
	2 => array(
		'id' => 444,
		'name' => 'Carlos'
	)
);
$smarty->assign('result', $result);

Iar in index.tpl trebuie sa scrieti urmatorul cod:

<select>
    {foreach $result as $row}
        <option value="{$row.id}">{$row.name}</option>
    {/foreach}
</select>

Aici observam ca variabila noastra, $result este folosita intr-o bucla foreach si valorile sunt reprezentate ca si$row. Din moment ce avem de a face cu un array multidimensional $row va la randul sau un array. Pentru a accesa un element dintr-un array, in Smarty trebuie sa folosim operatorul punct (.).

Instructiuni conditionale

Smarty permite folosirea instructiunilor conditionale precum {if},{elseif},{else}.Suporta si syntaxa mai avansata, de genul {if $number is not even} … {/if}

Sa presupunem ca in exemplul de mai sus dorim sa o selectam pe Jessica ca si valoare default in elementul de tip Select. Ar trebuii sa adaugam atributul boolean selected optiunii respective.

{block name=body}
    <h1>{$heading}</h1>
    <p>{$paragraph}</p>
    <div>
    <select>
        {foreach $result as $row}
            <option {if $row.id == 333}selected{/if} value="{$row.id}">{$row.name}</option>
        {/foreach}
    </select>
    </div>
{/block}

Dupa cum se poate observa mai sus, o instructiune conditionala IF este adaugata pentru a verifica daca id-ul este 333. Acesta nu prea este un exemple foarte bun. Hai sa incercam ceva mai practic. Ce trebuie sa facem daca dorim sa selectam valoarea pasata in $_GET[‘id’]?

{block name=body}
    <h1>{$heading}</h1>
    <p>{$paragraph}</p>
    <div>
    <select>
        {foreach $result as $row}
            <option {if $row.id == $smarty.get.id}selected{/if} value="{$row.id}">{$row.name}</option>
        {/foreach}
    </select>
    </div>
{/block}

Un alt lucru grozav la Smarty este acela ca poate prelua valori direct din array-urile superglobale precum:

  • $_SESSION
  • $_COOKIE
  • $_GET
  • $_POST
  • $_SERVER
  • $_REQUEST
  • $_ENV

Si lucrurile grozave ale acestui Template Engine nu se opresc aici. Smarty poate citi constantele direct cu syntaxa $smarty.const.NUME_CONSTANTA. Sunt sigur ca pana acum ati realizat ca aceasi treaba intr-un numar mult mai mic de linii de cod si ne-a luat mai putin timp.Escaping si delimitatorii Smarty

Vor exista momente in care va trebuii sa folositi acoladele si pentru altceva in afara de afisarea unei variabile.Exista 2 metode de a face acest lucru fara sa primim vre-o eroare Smarty. Putem folosi una dintre aceste 2 functii

Iata un exemplu pentru
{ldelim},{rdelim}

{block name=body}
    <h1>{$heading}</h1>
    <p>{$paragraph}</p>
    <div>
    <select id="names">
        {foreach $result as $row}
            <option value="{$row.id}">{$row.name}</option>
        {/foreach}
    </select>
    <script type="text/javascript">
		document.getElementById('names').addEventListener('change', function(){ldelim}
			alert(this.value);
		{rdelim}, false);
	</script>
    </div>
{/block}

Iar acum un exemplu pentru

{literal}{/literal}

{block name=body}
    <h1>{$heading}</h1>
    <p>{$paragraph}</p>
    <div>
    <select id="names">
        {foreach $result as $row}
            <option value="{$row.id}">{$row.name}</option>
        {/foreach}
    </select>
    {literal}
    <script type="text/javascript">
		document.getElementById('names').addEventListener('change', function(){
			alert(this.value);
		}, false);
	</script>
    {/literal}
    </div>
{/block}

Cam atat despre Smarty in acest tutorial, chiar daca nu am acoperit chiar atat de multe lucruri am discutat despre chestiile de baza. Oricum, cu siguranta vor mai exista tutoriale pe acest subiect.

Sunt un tanar programator din Bucuresti ce lucreaza in PHP/Mysql (MySqli/PDO), Laravel, CodeIgniter, MySQL, PostgreSQL, Wordpress, HTML5/CSS3, Sass, Photoshop si multe altele.
Google+ Community Facebook Group
Acest articol a fost mutat de pe vechea platforma.
Pentru orice eroare aparuta la mutare va rog sa ma contactati!