Czysty PHP vs Twig

Ponieważ framework symfony2 już jakiś czas temu miał swoją oficjalną premierę zacząłem się poważnie zastanawiać, czy nie oprzeć na nim kolejnego projektu. Jedną z nowości w stosunku do wersji 1.4 jest Twig – system szablonów, którego autorem jest Fabien Potencier, główny developer symfony. Zastanawia mnie, czy stosowanie Twiga rzeczywiście usprawnia tworzenie projektów, czy jest tylko zbędnym gadżetem?

Do tej pory w symfony szablony opisywałem w czystym PHP i nigdy nie doświadczyłem jakichś negatywnych skutków. Dlaczego zatem twórcy sf zdecydowali, że własny język używany do budowania widoków jest potrzebny? W jednym z artykułów na swojej stronie Fabien przytacza kilka argumentów. Przede wszystkim stwierdza, że PHP przestał być dobrym systemem szablonów. Na zasadzie porównań z Django przedstawia wady stosowania PHP do opisywania widoków.

Zwięzłość

Nawet tak trywialny przykład jak wyświetlenie zmiennej pokazuje, że PHP wymaga dłuższego kodu:

<?php echo $var ?>
{{ var }}

Gdyby jednak w PHP nie zrezygnowano ze skrótu wyświetlania, to wystarczyłoby napisać:

<?= $var ?>

Wtedy przewaga systemu szablonów byłaby moim zdaniem żadna.
Następne na tapecie jest filtrowanie wyjścia:

<?php echo htmlspecialchars($var, ENT_QUOTES, 'UTF-8') ?>
{{ var|escape }}

Jest krócej, to fakt. Ale coś tu jest chyba nie tak? Myślałem, że szablon ma odseparować logikę od widoku, a ew. czyszczenie i przetworzenie zmiennych należy przeprowadzić choćby w kontrolerze. A skoro tak, to po co mi do tego system szablonów?

Składnia zorientowana na szablony

Następny przykład – pętla:

<?php if ($items): ?>
  <?php foreach ($items as $item): ?>
    * <?php echo $item ?>
  <?php endforeach; ?>
<?php else: ?>
    No item has been found.
<?php endif; ?>
{% for item in items %}
  * {{ item }}
{% else %}
  No item has been found.
{% endfor %}

Ok, format Django jest krótszy, ale dla mnie jako programisty konstrukcja „for…else” jest conajmniej dziwna i mniej czytelna niż wersja PHP. Ciekawe też, czy w Django (a więc pewnie i Twigu) jest więcej takich „ficzerów”, czy to tylko jednorazowa funkcjonalność – tak na pokaz.

Ponowne wykorzystanie kodu

Fabien wspomina również o funkcji dziedziczenia szablonów.

<!-- base.html -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    {% block head %}
      <link rel="stylesheet" href="main.css" />
    {% endblock %}
  </head>
  <body>
    {% block content %}{% endblock %}
  </body>
</html>
 
<!-- index.html -->
{% extends "base.html" %}
 
{% block head %}
  {{ block.super }}
  <link rel="stylesheet" href="main.css" />
{% endblock %}
 
{% block content %}
  Index content
{% endblock %}

Zgadzam się, że to jest ciekawa funkcjonalność i dopóki samo PHP nie umożliwi innego sposobu wstawiania zawartości jak „include/require”, to osobiście uważam ją za przydatną. Co prawda system szablonów suma-sumarum i tak zamieni te wszystkie instrukcje na PHPowe „include”, ale łatwość definiowania wartości domyślnych akurat mi się podoba. Tutaj daję plus.

Bezpieczeństwo i sandbox

Tym razem autor porusza kwestię bezpieczeństwa i jako zaletę przytacza fakt, że symfony jako pierwszy framework dla web charakteryzował się automatycznym filtrowaniem, czy też „escapeowaniem” (dziwnie to wygląda) wyjścia. Co z tego, skoro po raz kolejny na warstwę widoku zrzuca się kwestie, za które moim zdaniem nie powinna ona odpowiadać. Oczywiście zależy, jaką główną funkcję naszym zdaniem ma spełniać system szablonów: jeśli ma ułatwiać i przyspieszać pracę, to może być dobre rozwiązanie. Ja natomiast system taki postrzegam jako mechanizm separowania różnych warstw aplikacji, którego zadaniem jest wyświetlanie odpowiednio przygotowanych danych, nie zaś ich obrabianie. Ma on jedynie ułatwić zadanie osobie projektującej layout. Nie rozumiejąc istoty, ani powodu umieszczenia niektórych zapisów może ona zwyczajnie usunąć pewne elementy szablonu. Zatem jaki rozsądny programista pozostawi grafikowi jedną z kluczowych kwestii bezpieczeństwa?

Pomijając powyższe, autor sam przyznaje, że domyślnie przyjęta polityka filtrowania wszystkiego, zamiast ułatwiać może uprzykrzać życie. W tym celu wprowadzono możliwość wyłączania omawianego mechanizmu na żądanie:

{% autoescape off %}
  {{ object.as_html }}
{% endautoescape %}

Wydaje mi się, że z domyślnym filtrowaniem może być więcej problemów niż pożytku – nie uważam tego za dobre rozwiązanie. Mam nadzieję, że w konfiguracji Twiga da się to jakoś wyłączyć.

Wyjątkiem może być tutaj „sandbox mode”. Jeśli nasza aplikacja z założenia musi pozwalać na osadzanie na stronie kodu wygenerowanego przez użytkownika, to tryb chroniony może się rzeczywiście przydać.

{% sandbox %}
    {% include "foo.twig" %}
    {% include "bar.twig" %}
{% endsandbox %}

Porównanie z innymi systemami szablonów

Jak nietrudno się domyślić, na stronie autora w porównaniu z konkurencją Twig zawsze wygrywa. Co z tego, jeśli w porównaniu autor nie umieścił najbardziej nas interesującego – czystego PHP. Mimo tego, że szablony Twiga są kompilowane do PHP, to podejrzewam, że programista musiałby być naprawdę kiepski, żeby stworzyć widok w PHP, który wydajnościowo przegrałby z takim samym generowanym przez system szablonów.

Jak zwykle – wszystko zależy…

Odniosłem wrażenie, że Twig jako podstawowy system opisu widoków w symfony2 jest rozwiązaniem dołożonym niejako na siłę, tylko dlatego, że taki jest obecnie trend. Jaki zatem może być sens stosowania systemu szablonów? Odpowiedź jest prosta: utrudniając pracę sobie, ułatwiamy życie grafikowi, czy projektantowi UI. Z pewnością elastycznemu programiście będzie łatwiej nauczyć się języka opisu szablonów by dostosować swoją wiedzę do potrzeb grafika, niż odwrotnie. Jeśli przyjazny wygląd aplikacji jest jednym z kluczowych wymogów stawianych przez klienta, to mając na uwadze dziedziczenie szablonów oraz ew. sandbox, warto rozważyć możliwość zastosowania mechanizmów Twiga. Przy dużych projektach, nad którymi pracuje zespół osób, gdzie można wyodrębnić grupę odpowiedzialną za UI, byłbym skłonny wykorzystać system szablonów na rzecz ułatwienia im pracy. W każdym innym wypadku raczej podziękuję i zostanę przy zwykłym, czystym PHP. Tak, czy inaczej, z czystej ciekawości na pewno wypróbuję Twiga, żeby zweryfikować wszystko, co napisałem.

Zaznaczam jeszcze raz, że Twiga dotąd nie używałem, a jedynie przymierzam się do jego wykorzystania. Opinię na jego temat opieram na materiałach zawartych na stronie autora projektu. Jeśli macie jakieś sugestie lub doświadczenia z używaniem systemów szablonów w PHP, ew. możecie podać inne „za” o „przeciw” – będę wdzięczny.


O Autorze
Nazywam się Łukasz Modliński. Od ponad 10 programuję aplikacje bazodanowe dla Web. Zawodowo zajmuję się głównie budową informatycznych narzędzi wspomagania zarządzania.

Skomentuj