Régebben írtam a PHP sablonnyelvként való használatáról. Lehet szépíteni a dolgokat, de hosszú távon ennek a használata (főleg megfelelő szerkesztőprogrambeli makrók nélkül) kényelmetlen, hosszadalmas és még a makrók használatával együtt is csúnya, olvashatatlan. A Smarty egyetlen pozitívuma az, hogy egyszerűen és gyorsan lehet írni, kényelmesen lehet használni. Persze ez nem vigasz azoknak, akik nem akarnak egy több ezer kódsorból álló sablon kezelőt használni csak emiatt a kényelem miatt.
Nagyrészt így vagyok vele én is. Gyakorlatilag a szintaktikájának az alapjait leszámítva nem lenne szükségem semmire a Smarty-ból. Nem érdekel, hogy korlátozni lehet a sablon íróját, hogy a PHP eszköztár csak egy részét használhassa (minek is korlátoznám magam...). Nem érdekel, hogy könnyen és gyorsan lehet hozzá plugineket írni (ha az egész PHP használható lenne, erre nincs is túl nagy szükség). Nincs szükségem semmi ilyesmire.
Sokkal inkább vonz az, ha a nyelvet gyorsan lehet gépelni (pl. mert rövid, minimális speciális karaktert használ és logikus a szerkezete). Az se egy hátrány, ha az elkészült sablon valamilyen szinten olvasható lesz. Nem lenne rossz még, ha egy elfogadható minőségű PHP kódot generálna az én sablonomból, ami aztán elfogadható (a lehető leggyorsabb) sebességgel futna. Az első kettőt még csak-csak teljesíti, de az utolsóval eléggé hadilábon áll a Smarty. Így itt az idő valami más után nézni...
A legkézenfekvőbb dolog a PHP használata lenne erre a célra, ami az első két ponton totálisan megbukik. Kiindulási alapnak viszont jó lesz:
<h1>Valami sablon</h1>
<?php if (5 > 6): ?>
<p><?php print('5 nagyobb mint 6'); ?></p>
<?php else: ?>
<p><?php print('5 nem nagyobb, mint 6'); ?></p>
<?php endif; ?>
Mi lenne, ha első körbe a <?php és a ?> helyett a jól megszokott { és } lenne használva?
<h1>Valami sablon</h1>
{ if (5 > 6): }
<p>{ print('5 nagyobb mint 6'); }</p>
{ else: }
<p>{ print('5 nem nagyobb, mint 6'); }</p>
{ endif; }
Haladunk, esetleg még a print() helyett bevezethetnénk a PHP rövid tag <?= szerkezetéhez hasonlóan egy {= szerkezetet:
<h1>Valami sablon</h1>
{ if (5 > 6): }
<p>{= '5 nagyobb mint 6' }</p>
{ else: }
<p>{= '5 nem nagyobb, mint 6' }</p>
{ endif; }
Pár kényelmességet elősegítő lépés múlva (szóközök, kettőspontok, felesleges zárójelek, pontosvesszők eltűntetése) sikerült eljutnom a végleges formáig:
<h1>Valami sablon</h1>
{if 5 > 6}
<p>{='5 nagyobb mint 6'}</p>
{else}
<p>{='5 nem nagyobb, mint 6'}</p>
{if}
Rémisztően hasonlít a Smarty-ra (ez valamilyen szinten cél is volt :)), viszont az ebből fordított PHP kód gyakorlatilag egy az egyben megegyezik az általunk írt sablon kód szerkezetével. Most, hogy megvan az alapvető szintaxis, jöhet a sablonkezelő osztály, ami a fentebb említett több ezer sorhoz képest megvalósult úgy 170 sorból (milyen csodákra képes, ha kihagyunk minden "szemetet", amire nincs szükségünk :)), ami már tartalmaz pár extra funkciót is (mint például a lefordított sablonok újrafordítási szükségességének ellenőrzését). A bemenete egy ilyen template, amiből ezt a PHP kódot generálja, valami ilyesmi kóddal:
<?php
include('lighty.php');
$l = new Lighty();
$l->assign('list', array('a', 'b', 'c', 'd'));
$l->display('teszt.tpl');
?>
Amit érdemes ezzel kapcsolatban megemlíteni, hogy a lefordított forrás első sorának elején ott van egy kommentben a fordítás ideje, ami az újrafordítás-ellenőrző számára fontos. Valamint az egész fájl egyetlen egy PHP kódblokkot tartalmaz (ami emlékeim szerint optimálisabb, mint sok-sok kis PHP kódblokk egy sablonon belül). Emiatt vannak felesleges, csak whitespace karaktereket kiíró print() hívások, de ezek megszüntethetőek. És végül, de nem utolsó sorban, a Lighty névre keresztelt sablonrendszer első publikus verziója letölthető innen. A csomagban megtalálható egy teszt.php is, ami a fentebb felvázolt példakódot tartalmazza, valamint az általa használt template fájlok és szükséges könyvtárak is.
És hogy így a végén még a címben említett kérdést is megválaszoljam: szerintem szükség van a sablonnyelvekre, mert nagyban meg tudják könnyíteni az ember életét az által, hogy meggyorsítják a sablonírás folyamatát.
Ezt az írást követte el 13:41-kor. Kommentelj! 

Hasonszőrű problémával hadakozom magam is, ebből kifolyólag dupla hálás köszönet a "Könnyűkéért" :)
Két kisebb bugfix történt:
- a 87. sor környékén a fetch() visszatérése volt hibás
- a 101. sor környékén a display() függvényben az array_merge() visszatérési értéke nem volt felhasználva
A fenti linken már a javított verzió tölthető le.
Hmm. Hát nekem elég ellentmondásos az írás. A sablonnak nem az az elsődleges szerepe, hogy gyorsabban lehessen php kódot gépelni. Persze lehet ez is cél, de a smarty-t nem lehet ide sorolni. Ezért az összehasonlítás is értelmetlen.
Amúgy hasznos lehet a Lighty :)
Persze, az elsődleges szerepe az lenne, hogy a megjelenítési réteget elválasszuk az alkalmazás többi részétől. De ez már megvalósul(hat) akkor is, ha a PHP-t használjuk, mint sablonnyelvet (ahogy azt nem egy keretrendszer teszi).
Viszont azt - szerintem - ritka kényelmetlen gépelni és ezért is keletkezett az igényem a Lighty-ra... :)
Történt pár módosítás a rendszerben:
- alkönyvtárakba rendezett template fájlok kezelése,
- üres file, lighty blokkot nem tartalmazó fájl lefordításának javítása.
A fenti linken már a javított verzió tölthető le.
Szia!
Nagyon jó kis cuccot raktál össze! Én néhány módosítást tennék azért bele:
- a compileCheck ne nézze a template módosítás dátumát, hanem csak akkor fordítsa újra a templatet, ha a cacheben nincs. debug szempontjából a mostani nyílván jobb megoldás, de később működő rendszernél sztem felesleges teljesítmény veszteség
- trigger error helyett dobhatna Exceptiont
- lehetne hozzá konstruktor vagy factory pattern, ha a templatek több különböző könyvtárakban vannak
D.
Lehet újra kellene értelmezni a compileCheck-et, hogy FALSE esetén sose fordítson újra, ha létezik a template, TRUE esetén meg végezze ezt az ellenőrzést. Vagy inkább egy reCompile változót bevezetni helyette, ami ha TRUE mindig újrafordít, ha FALSE akkor sose.
Azért döntöttem a trigger_error mellett, mert ezeket a dolgokat a fejlesztés alatt úgyis ki akarja javítani az ember, nem tartok valószínűnek egy olyan esetet, hogy nem létező template esetén keletkező kivételt el akarnék kapni és valami mást csinálni abban az esetben.
A beállítások azért lettek public-ok, hogy ne kelljen konstruktorban átadni őket, hanem példányosítás után lehessen változtatni. De persze ízlés kérdése, hogy az ember milyen megoldást választ, nálam a keretrendszer példányosítja a sablonozót, és beállítja a két könyvtárat, amit használ és egy könyvtáron belül (alkönyvtárakban) vannak a sablonok.
Köszi az észrevételeket, a compileCheck-el mindenképpen kezdek valamit, meg van még pár ötletem, amit le kéne kódolni, úgyhogy hamarosan talán lesz új verzió... :)
Hajrá, hajrá! Várom! :)
Amúgy az errorral meg kivétellel kapcsolatban annyit, hogy nekem jobban tetszik a nem script nyelvek szemlélete (C#, Java). Arra gondolok, hogy hiba akkor keletkezik, ha fordítási időben van valami gond, exception meg akkor, ha futási időben történik valami gebasz. Mivel a fatal_error stb és társait nehéz elkapni PHP-ben, és nem túlságosan OOP szemléletű, ezért javasoltam az Exceptiont, amit viszont el lehet kapni keretrendszeren belül és le lehet nyelni, vagy ki lehet rakni egy "ízléses" exception oldalt (pl. asp.net). De ez már tényleg egyéni felfogás kérdése.
Nos megszületett az 1.1.0-s verzió. A következő dolgok változtak:
- compileCheck helyett reCompile lett, a fentebb írt működéssel
- lett egy Lighty::shortcuts tömb, amivel lehet rövidíteni adatkiírások során. Például a {h='szöveg'}-ből print(htmlspecialchars('szöveg')); lesz (a tömb public, szóval lehet saját függvényekkel tovább bővíteni).
- removeHtmlComment beállítása esetén már nem szedi ki az IE feltételes megjegyzéseket
A kivételeken még agyalok, hogy legyen-e, és ha igen, akkor hogyan. Egyelőre maradt a trigger_error-os megoldás.
az jutott eszembe, hogy szerintem jó lenne, ha többlépcsőssé lenne tehető a sablon objektum. arra gondolok, hogy az Lighty::assign() nem csak sztringet, hanem másik Lighty objektumot is tudna fogadni, így jobban átláthatóvá válnának a template fájlok.
vagy te hogy csinálod?
közben látom a fetch()-t :)
A $l->assign('nev', $valtozo) esetén a $valtozo akár egy (Lighty) objektum is lehet, amit a templateben $nev -ként lehet elérni, bár őszintén szólva nem látom ennek értelmét/hasznát.
Jó cucc, viszont a shortcutokat nem érdemes használni, maximum statikus szövegek esetében, mivel tetszőleges kódfuttatásra adhat lehetőséget. Íme egy példa:
Ebből a kódból :
{a="Ez egy teszt".phpinfo()}
Ezt generálja:
print(addslashes("Ez egy teszt".phpinfo()));
Persze ezen is lehet segíteni egy kis input szűréssel, de inkább nem javaslom, a rövidített függvények használatát a kódban.
scripter-man
Nem igazán értem ez hol jelenthet problémát. Ha magadnak írsz ilyet a sablon kódban akkor ezt az eredményt várod. Kívülről meg most így hirtelen úgy gondolom, hogy nem érkezhet olyan input, aminek ez lenne a végeredménye.
$lighty->assign('valami', '"Ez egy teszt".phpinfo()');és
{a=$valami}esetén
print(addslashes($this->templateVariables['valami']));lesz, ami a
print(addslashes('"Ez egy teszt".phpinfo()'));kódnak felel meg. Persze a
$lighty->assign('valami', "Ez egy teszt".phpinfo());esetén más a helyzet, de azzal meg ugyanott vagyunk, hogy nem érkezhet ilyen input kívülről.
Smartynak alapvetően az a baja, hogy a fejlesztői nem tudnak programozni, vagy csak nem gondolták át eléggé a rendszert. A felülete kényelmes, de ami alatta van, az gáz.
Az alap compilert 150 sorból simán ki lehet hozni, a függvényeket (úgy, mint if,foreach,include,comment...) pedig további párszáz sorból. Ehhez képest kb 5000 sor a mostani Smarty, és a sebessége is olyan...
Ez eléggé jónak tűnik, én egy egyszerű sablonkezelőt használok ami a elemeket cseréli minta szerint, debug mód kikapcsolása esetén meg a fölösleget eltünteti, de ez mindenképpen egy használható ötlet itt.
Már több projektnél is használtam ezt a sablonrendszert. Egy folyamatban lévő saját esetben pedig már tovább fejlesztettem, így már képes nyelvi támogatásra is úgy, hogy a lefordított kódban már a szövegek vannak benne. Elsőre persze nem így csináltam, de hamar rájöttem, hogy 2 nyelvi függvény hívás gyorsabban lefut, mintha ugyanezt az 5000 ciklusos for ciklusban teszi 10000-szer. :D
Illetve ezen kívül van még benne automatikus link (href) transzformáció is, szintén nyelvi támogatás keretein belül, hogy mindenki a saját nyelvén lásson szép url-t. :)
Sajnos perpillanat erősen össze van építve a keretrendszer többi részével, ezért nem tudom megmutatni a kódot, de ha időm engedi készítek róla egy cikket, hogy hogyan lehet könnyedén bővíteni a Lighty tudását. :)