Template engine, doen of niet doen?
Ik ben momenteel bezig een simpel CMSje te maken die ik voor xxx aantal websites nodig ga hebben en waar het doel is zo snel mogelijk sites te maken. Omdat er een designer bij komt die veel weet van HTML en CSS maar niet al te veel weet over PHP zat ik er aan te denken om een template engine te gaan gebruiken zodat hij zelf ook het e.e.a. voor elkaar weet te krijgen. Punt is alleen, is dat handig?
Er zijn op het internet tal van discussies gaande over wat beter is, of PHP zelf een template taal is en of een abstractie bovenop PHP ( in de vorm van een template taal ) niet overkill is.
Persoonlijk zie ik door de bomen het bos niet echt meer en er zijn ook xx aantal template engines die er te gebruiken zijn. Ik ben dan ook op zoek naar jullie mening over PHP en of een template engine daarbovenop nodig is. Als dit inderdaad een snellere workflow oplevert, dan doe ik waarschijnlijk wel, niet kijkende naar de verminderde prestaties van de requests. Sneller sites opleveren is hier namelijk een sleutelwoord.
Mochten jullie een template engine kennen die echt goed werkt en vooral niet te veel overhead heeft (lees: hoge leercurve) aarzel dan niet om die hier te benoemen.
Als ik iets ga gebruiken, dan vooral geen Smarty of Twig en liever ook niet iets dat de eval() functie gebruikt. Dat zijn mijn persoonlijke voor( of af)keuren.
Dus kort:
1. Template engine, wat zijn jullie ervaringen?
2. Is het de moeite waard?
3. Wat zijn de (resource) kosten?
4. Leercurve, is het de moeite waard?
5. Prestaties en vooral geen zware overhead / PEAR package achtige installaties
Allemaal alvast bedankt :)
PHP is zelf een template taal is natuurlijk wel waar, maar ook wel eentje met een hoge leercurve. PHP is nou niet heel simpel als iemand alleen HTML en CSS kent. Twig is dan bijv. een stuk simpeler als je overweg kan met engels:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
===layout.twig
<body>
{% block body %}
some default text
{% endblock %}
</body>
===welcome.twig
{% extends 'layout.twig' %}
{% block body %}
<h1>{{ pagetitle }}</h1>
{% for post in posts %}
<article>
<h2>{{ post.title }}</h2>
<time pubdate>{{ post.publishDate }}</time>
<p>{{ post.intro }}</p>
</article>
{% endfor %}
{% endblock %}
<body>
{% block body %}
some default text
{% endblock %}
</body>
===welcome.twig
{% extends 'layout.twig' %}
{% block body %}
<h1>{{ pagetitle }}</h1>
{% for post in posts %}
<article>
<h2>{{ post.title }}</h2>
<time pubdate>{{ post.publishDate }}</time>
<p>{{ post.intro }}</p>
</article>
{% endfor %}
{% endblock %}
Vind ik toch zeer begrijpelijk voor een server-side leek.
Over de syntax, die van Twig en Smarty zijn inderdaad erg prettig en ook nog eens leesbaar en dat zou inderdaad een reden zijn om ze wel te gebruiken. Maar ik zie liever een simpele class of een kleine verzameling classes die met soortgelijke syntax werken.
Prestaties zijn eigenlijk niet een geldige reden, een template engine is altijd slomer dan PHP zelf, maar een simpelere syntax is voor de designers een stuk makkelijker werken en neemt de dev team straks werk uit handen.
Voor beide aanpakken valt iets te zeggen, vandaar dat ik hier meningen wil horen en voorkeuren. Twig is geen slechte engine maar RainTPL bijvoorbeeld is een stuk sneller en kost ook veel minder moeite om te implementeren.
Was is er mis met twig dan? Hoe de compiler eruit ziet is irrelevant, hoe de gecompileerde php code eruit ziet des te meer en die is bij twig (optimaal) clean...
En verder: als je twig te lastig vind om te implementeren, kan je beter gaan borduren dan serieus PHP schrijven.
Toevoeging op 02/03/2012 18:40:58:
Ik heb btw geen speciale voorkeur voor twig, maar de gebruikte tegenargumenten slaan niet echt hout.
Punt echter, blijft wel dat de overhead en leercurves hoger liggen voor Twig, Smarty en anderen vergeleken met de simpele template engines.
Komen we toch terug bij de redenen waarom wel of niet. Daar is namelijk nog niemand die er een mening over heeft.
== PHP als template parser ==
Het is met PHP goed mogelijk om HTML en PHP code te combineren. Op deze manier kan je PHP ook gewoon als template parser gebruiken. Dit heeft een aantal voordelen:
- Het is razend snel. Je hebt geen overhead van een template parser
- Je hoeft geen nieuwe taal te leren
- Je krijgt nette color coding in je editor
Helaas zijn er ook wat nadelen:
- Je gaat snel te veel in je templates doen. Je moet dus behoorlijk veel discipline hebben
- Je kan geen code blokkeren
- Voor designers is de leercurve hoger
- Sommige dingen zijn in PHP gewoon behoorlijk ingewikkeld te bereiken. Denk hierbij aan dingen als auto escaping en template overerving.
Een deel van deze problemen zijn natuurlijk op te lossen door speciale functies te schrijven die je in je templates kan gebruiken.
== Wel een template parser gebruiken ==
Gezien de grote hoeveelheid template parsers beschikbaar in PHP, zijn er dus kennelijk ook genoeg redenen om ze te gebruiken. Dat is dan ook zo. Een template parser heeft een aantal voordelen namelijk ten opzichte van PHP gebruiken:
- Een template parser kan auto escaping doen. Dit betekent dat zonder anders aangegeven alles wat weergegeven wordt gestript wordt van HTML. Op deze manier heb je minder snel XSS bugs
- Een template parser kan in een sandbox modus draaien. Je kan voorkomen dat bepaalde codes uitgevoerd worden
- De leercurve voor designers is lager. Ze hoeven namelijk geen PHP te leren, maar hoeven alleen de eenvoudigere taal te leren
- Je kan functionaliteit implementeren die in PHP templates heel lastig na te bootsen is. Zoals template overerving!
- Je dwingt een duidelijke scheiding tussen de weergave en je business logic af
Nadelen van template parsers zijn:
- Je moet als je alleen programmeert een extra taal leren. Meestal zal dit echter geen probleem hoeven op te leveren.
- Ze zijn trager dan PHP zelf
=== Twig ===
Zelf gebruik ik tegenwoordig altijd een template parser. Namelijk twig. Hier heb ik een aantal redenen voor:
- Twig is heel eenvoudig. Zeker vergeleken met de bekendere template parsers in PHP zoals Smarty
- Twig ondersteunt template extensie. Dit is een must voor mij. Je kan een base template definieren. Hierin geef jebepaalde blocks aan. Vervolgens kan je vanuit een andere template deze base template overerven en de blocks overschrijven. Zo hoeft mijn code alleen maar een specifieke template te laden voor dat stuk code. De template gaat vervolgens zelf de base template overerven zonder dat mijn code hiervan af te weten. Dit maakt mijn code dus heel erg simpel
- Goede caching. Alle templates worden gecompileerd naar PHP waardoor ze razend snel zijn. De code die Twig bij het compileren genereert is behoorlijk duidelijk en overzichtelijk
- Auto escaping. Nog een must voor mij. Zeker als je met designers werkt. Alle variabelen die ik binnen mijn template gebruik worden geescaped. Ik hoef dus geen htmlspecialchars() of iets dergelijks te doen. Mocht je dit niet willen is het mogelijk om dit per variabele expliciet aan te geven. Dan zal je het alleen zelf moeten doen.
- Zeer duidelijke template syntax. Één van de beste die ik tot nu toe gezien heb
- Heel eenvoudig uit te breiden. Twig is heel eenvoudig opgezet waardoor het eenvoudig is om zelf commando's toe te voegen. Zonder dat je helemaal in de code moet gaan hacken. Tot nu toe heb ik alles wat ik wilde kunnen bereiken met Twig.
Quote:
Punt echter, blijft wel dat de overhead en leercurves hoger liggen voor Twig, Smarty en anderen vergeleken met de simpele template engines.
Als je het niet probeert kan je ook nooit erover oordelen. Hoe weet je bijv. dat de leercurve hoger is dan bij "simpelere" template parsers als je het niet uitprobeert?
Mijn ervaring is als volgt:
- Jou "simpelere" template parsers kunnen maar heel weinig waardoor ze onbruikbaar worden omdat je allerlei dingen in je business code moet gaan doen die eigenlijk met de weergave te maken hebben. Daarnaast zijn ze vaak nog trager ook
- De overhead van Twig ligt lager omdat deze parsers geen caching en compiling geburiken.
Het is even een investering, maar als je een CMS wil bouwen, moet je sowieso wel wat PHP kennis hebben en moet dat echt geen probleem opleveren. Daarnaast vond ik zelf Twig super eenvoudig te implementeren. De documentatie is zeer goed en als je gewoon de code daaruit exact kopieert werkt het al.
Ja, ik ben erg blij met je bericht, ik denk dat ik Twig eens ga bekijken. Heb je nog goede resources beschikbaar om me in te kunnen lezen?
Ps. de rest mag vrolijk mee discussieren hoor, niets staat vast!
Het is extra overhead, performance-killing en met een beetje discipline en een goed framework gebruik je view helpers om code in je views te voorkomen.
Ik was vroeger fan van Smarty, en het is een goede template taal (net zoals Twig, die is iets sneller) maar nu ik een tijdje zonder werk zie ik niet meer in waarom ik uberhaubt een template taal zou gebruiken, maakt het in mijn ogen alleen maar complexer.
Wat wel aan te raden is om de PHP shorttag in te schakelen en if, foreach statements anders te schrijven voor de leesbaarheid:
Code (php)
Gewijzigd op 02/03/2012 21:32:44 door kees Schepers
Er zal weinig templating nodig zijn, hooguit een paar variabelen, soms een loopje en dat moet snel kunnen, dan kan ik dat zelf gaan doen, maar liever werk ik niet aan de html die hij aan het schrijven is dus vandaar dat ik een template taal overweeg.
Over serverside overhead en CPU maak ik me niet al te druk, het gaat vooral om leadsites, weinig traffic en alle domeinen komen via 1 database. Of nouja, de code voor de templates komt via 1 CMS, daar kunnen alle websites worden beheerd.
De php short code is ook nog een alternatief, daar zit ik ook nog over te twijfelen, ik wou zelf alleen wel bepaalde templates in eigen beheer houden voor bijvoorbeeld berichtjes als: "email is verstuurd" of "Je hebt geen achternaam opgegeven". Dat soort dingen. Dat moet hij wel makkelijk kunnen benaderen en aanpassen en doorheen lopen.
Maar in jouw situatie kan ik me er goed in vinden dat je twijfelt. Misschien dat je ook de designer kan vragen wat hij het fijnste vindt? Of werkt hij nog niet bij jullie?
Ik moet wel eerlijk zeggen dat ik met het voorbeeldje van Wouter wel wat moeite heb. Het ziet er voor mijn gevoel niet simpeler uit, maar ik ben Smarty gewend dus wellicht komt mijn verwarring daardoor.
Ik geloof wel dat Twig het beste performance bood.
Heb nog een interessante link gevonden: http://www.phpcomparison.net/
http://twig.sensiolabs.org/
Vooral de caching is in Twig natuurlijk erg handig. In dev. mode kun je de cache uitzetten, maar in production mode kun je de cache aanzetten. Na 1 bezoeker zijn alle pagina's gecached met hun gegevens in een map en die wordt om de zoveel tijd ververst, het voordeel daarvan is dat het dus niet telkens door de parser heen moet.
@Kees, het voordeel van templates parsers vind ik zeer goed uitgelegd door Mark. Je kunt dingen gebruiken die niet in simpele php kunnen, je kunt de designer beperken, zodat ze niet foute dingen gaan gebruiken, en de syntax is makkelijk en lijkt veel op JS of, wat designers meer zal aanspreken, jQuery. Het voordeel daarvan is dat de leercurve al een heel stuk omlaag gaat.
Veel informatie over de Twig syntax en het installeren van twig is hier te vinden: Vooral de caching is in Twig natuurlijk erg handig. In dev. mode kun je de cache uitzetten, maar in production mode kun je de cache aanzetten. Na 1 bezoeker zijn alle pagina's gecached met hun gegevens in een map en die wordt om de zoveel tijd ververst, het voordeel daarvan is dat het dus niet telkens door de parser heen moet.
@Kees, het voordeel van templates parsers vind ik zeer goed uitgelegd door Mark. Je kunt dingen gebruiken die niet in simpele php kunnen, je kunt de designer beperken, zodat ze niet foute dingen gaan gebruiken, en de syntax is makkelijk en lijkt veel op JS of, wat designers meer zal aanspreken, jQuery. Het voordeel daarvan is dat de leercurve al een heel stuk omlaag gaat.
De designer beperken, kan ik me in vinden op zich. Ik vindt de syntax niet makkelijk en al helemaal niet op JS lijken? althans niet die van Twig? Dus wat betreft de leercurve omlaag brengen ben ik niet helemaal met je eens.
Voorbeeldjes:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Twig for post in posts
JS for( post in posts )
Twig post.title of post['title']
JS post.title of post['title']
Twig set foo = [1,5,6]
JS var foo = [1,5,6]
Twig set foo = {'foo' : 'bar', 'bar' : 'lorem'}
JS var foo = {foo : 'bar', bar : 'lorem'}
JS for( post in posts )
Twig post.title of post['title']
JS post.title of post['title']
Twig set foo = [1,5,6]
JS var foo = [1,5,6]
Twig set foo = {'foo' : 'bar', 'bar' : 'lorem'}
JS var foo = {foo : 'bar', bar : 'lorem'}
>> Waarom zou je geen dingen kunnen gebruiken die in simpel PHP niet kan? Kan dit niet gewoon met view helpers?
Probeer jij maar eens het exclude systeem met blocks na te bouwen in simpele PHP, zodat elke designer het kan. En dan ook nog met default waardes, ik denk niet dat het heel erg makkelijk gaat worden...
Gewijzigd op 02/03/2012 23:35:08 door Wouter J
Wat betreft het 'lijken' op JS doelde ik vooral op de % tekens in je bovenste voorbeeld. In dit voorbeeld lijkt het inderdaad al veel meer.
Wat betreft je laatste opmerking, ik heb zeg ook; dat ik geen reden zie om een template systeem te gebruiken als je niet met designers werkt (dan vindt ik het nog wel enigzins discutabel) dus ik denk dat we dat betreft het wel met elkaar eens zijn hoor!
Wat bedoel je met het exclude systeem? Ik denk dat je met die bewering wel uit gaat van het niet gebruiken van een degelijk framework want daar kun je hetzelfde mee als helpers in een template systeem.
Nu ben ik een tijdje Symfony aan het uitproberen, en die heeft Twig. Dus je kan inderdaad niet zeggen dat ik veel ervaring heb met view helpers. Maar het lijkt mij dat zo'n exclude systeem, waarbij je 1 file in het andere laad en doormiddel van blocks duidelijk maakt waar de content komt, niet in een begrijpelijke syntax voor beginners te maken is.
Twig heeft inderdaad andere open en sluit tekens:
Code (php)
1
2
3
2
3
{{ someVar }} // {{ is hetzelfde als <?=someVar?>
{% %} // staat alle logische dingen in, dus for loops enzo, te vergelijken met <?php ?>
{# #} // een comment in Twig, zelfde als <?php # ?>
{% %} // staat alle logische dingen in, dus for loops enzo, te vergelijken met <?php ?>
{# #} // een comment in Twig, zelfde als <?php # ?>
Maar als je die weg denkt lijkt het erg op JS.
Of bedoelen jullie een frontend webdeveloper ? Ik zie een traject zo voor mij: (overleg met klant en dergelijke even weggelaten)
- Realisatie design (dit doet een designer)
- Templaten van het design (dit doet een fontend webdeveloper)
- Implementeren van de functionaliteiten (dit doet een backend webdeveloper / applicatie ontwikkelaar)
Om die reden gebruik ik dus geen Template parser. Maar zoals Mark zegt moet je daar wel discipline voor hebben. Tja, het leven van een programmeur gaat natuurlijk niet over rozen ;-)
- Template inheritence
- Auto escaping
Beide niet eenvoudig na te bootsen met PHP templates icm view helpers. Met name kwa efficientie na het kopieëren niet.
=== Template inheritence ===
Dit is over komen waaien uit het Object Georienteerd programmeren en als eerste geimplementeerd in het Python framework Django (daar is Twig ook weer op gebaseerd). Het is hier mogelijk om blocks in een template te definieren. Vervolgens kan je deze template overerven vanuit een andere template en de blocks overschrijven. Het idee is simpel, maar wel enorm krachtig. Zo hoeven mijn actions binnen het framework namelijk niets meer af te weten van een layout of een base template.
Voorbeeldje:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html>
<head>
<title>{% block title %}{% endblock %}</title>
{% block css %}
<link rel="stylesheet" type="text/css" href="css/design.css" />
{% endblock %}
</head>
<body>
<ul id="menu">
<li>Home</li>
</ul>
<div id="content">
{% block content %}{% endblock %}
</div>
{% block js %}
<script type="text/javascript" src="js/jquery.js"></script>
{% endblock %}
</body>
</html>
<head>
<title>{% block title %}{% endblock %}</title>
{% block css %}
<link rel="stylesheet" type="text/css" href="css/design.css" />
{% endblock %}
</head>
<body>
<ul id="menu">
<li>Home</li>
</ul>
<div id="content">
{% block content %}{% endblock %}
</div>
{% block js %}
<script type="text/javascript" src="js/jquery.js"></script>
{% endblock %}
</body>
</html>
Vervolgens kan ik vanuit een andere template delen overschrijven:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
{% extends "base.html" %}
{% block title %}Andere titel{% endblock %}
{% block css %}
{{ parents() }}
<link rel="stylesheet" type="text/css" href="css/specifieke_pagina.css" />
{% endblock %}
{% block content %}
<!-- pagina content -->
{% endblock %}
<!-- Geen javascript toe te voegen, dus dat block overschrijf ik niet -->
{% block title %}Andere titel{% endblock %}
{% block css %}
{{ parents() }}
<link rel="stylesheet" type="text/css" href="css/specifieke_pagina.css" />
{% endblock %}
{% block content %}
<!-- pagina content -->
{% endblock %}
<!-- Geen javascript toe te voegen, dus dat block overschrijf ik niet -->
In mijn action zal ik alleen die tweede template aanroepen en die template bepaalt vervolgens zelf weer welke template er geladen moet worden.
=== Auto escpaping ===
Alle waarden die ik in Twig weergeef worden automatisch geescaped mits niet anders aangegeven:
Bij het compilen wordt vervolgens netjes naar PHP omgezet op de manier zoals je zou verwachten. Bij een PHP template kan je auto escaping wel instellen, maar dan is het weer heel lastig om het te omzeilen of je krijgt overal $this->escape($var) in je template.
Het inschakelen van short_tags is verder ten strengste af te raden. Dit levert namelijk problemen op zodra je met XML files gaat werken. Vanaf PHP 5.4 is er wel een optie om alleen de <?= notatie in te schakelen.
=== Framework gebruiken == geen templates ===
Ik ben het niet eens met het statement dat een framework gebruiken direct het gebruik van templates overbodig maakt. Het is niet voor niets dat elk framework in PHP gebruik maakt van templates. Hetzij PHP templates, hetzij een andere template parser. Het framework zorgt ervoor dat je verdere code op een standaard manier gestructureerd is zodat het voor derden die ook het framework kennen eenvoudiger aan te passen is. Daarnaast zal het je wat tijdwinst opleveren met ontwikkelen op het moment dat je het framework onder de knie hebt. De learning curve van de verschillende frameworks is namelijk behoorlijk stijl.
Een goed voorbeeld van het combineren van een framework met een template parser is Symfony 2 waar tegenwoordig standaard Twig gebruikt wordt :)
Edit:
Je zit hier PHPHulp al hoe die mis gaat!!! Ik gebruik een shorttag en er wordt direct vanuit gegaan dat ik een code block wil starten
Gewijzigd op 04/03/2012 14:45:56 door Mark Kazemier
Verder een erg goed en duidelijk verhaal!
@Mark, dat in Symfony Twig wordt gebruikt is niet heel verbazingwekkend. Het is allebei namelijk van de zelfde maker/bedrijf... Wel een goed framework trouwens.
Gewijzigd op 04/03/2012 15:07:27 door Wouter J
Wat betreft auto escaping, in Zend Framework 2 zit dit standaard (zonder template engine) en in Zend Framework 1 kun je dit zeer eenvoudig zelf maken door gebruik te maken van Stream wrappers. In mijn eigen uitbreiding op ZF zit het al. (Pike_View_Stream).
En Zend Framework implementeert standaard geen template taal in ieder geval. Daar wordt dus standaard geen template engine gebruikt.
Template talen zijn (bij voorkeur) onnodig, maar ik zie hier op dit moment de voordelen wel van in. Een designer moet er ook goed mee overweg kunnen. Ik kan ze wel een basis in PHP gaan geven maar dingen als escaping (niet eens bij stil gestaan..) doen me de das om. Een template taal levert toch meer voordelen op als het gaat om de scheiding tussen logica en presentatie en dat is denk ik het belangrijkste dat je hier mee wint.
Over de view_helpers, ik heb me er voor deze discussie nooit in verdiept en het idee lokt me ook wel maar in de basis doet het precies hetzelfde als wat elke template taal doet, wat een template taal als extra "functionaliteit" heeft is een scheiding tussen eerdergenoemde logica en presentatie.
Zoals het er nu naar uit ziet ga ik wel een template taal gebruiken, welke waarschijnlijk Twig wordt:
1. Twig
2. RainTPL
Twig heeft de extra voordelen van inheritance, wat waarschijnlijk erg lastig uit te leggen valt aan designers, maar functionaliteit die wel verdomd handig is. De syntax vind ik in beide gevallen wel netjes al zal het natuurlijk eigen voorkeur zijn.
Iedereen bedankt voor de berichten en als ik een keuze heb gemaakt, zal ik het laten weten.
Wat schort er precies aan mijn ongenuanceerde mening? De compile tijd van de template engines doet er niet toe, alleen de tijd die nodig is om gecompileerde templates te renderen en aangezien dat gewoon plain PHP is kan de pagina worden weergegeven met een minimale overhead (template zoeken, cache valideren), die in het niet valt bij 1 enkele DB query.
En dat het lastig op te zetten is? Al eens naar Doctrine, Symfony2 of een LAMP stack gekeken?
@kees
Hoe wordt die auto-escaping dan in plain PHP geïmplementeerd? Gewoon Controller#get($var, $raw = false); ?
En hoe heb je het zelf gedaan? fread('input://var') ? Lijkt me niet echt de mooiste optie, toch?