• Trennung von Inhalt, Logik und Layout mit patTemplate

    von am 11. November 2008

    Manchmal geschieht es, dass Träume war werden. Ein alter Traum im World-Wide-Web ist es die Dreieinigkeit von Inhalt, Logik und Layout zu trennen und immer wieder werden Technologien vorgeschlagen die diesen Traum verwirklichen sollen. Eine besonders erfolgreiche Technologie sind Cascading Style Sheets, die es weitestgehend ermöglichen die semantischen Inhalte von der bildhaften Gestaltung einer Web-Seite zu trennen. Die CSS-Designer-Web-Seite mag hier als Beispiel dienen wie unterschiedlich der selbe HTML-Code allein durch das Austauschen der CSS-Dateien dargestellt werden kann. In wie weit sich die hier präsentierten Schmuckstücke auf reale Problem anwenden lassen sei einmal dahin gestellt. Fakt ist, CSS hat dem Wahnsinn der verschachtelten Tabellen-Layouts ein Ende bereitet und das Arbeitsleben eine HTMLers um einiges komfortabler gestaltet.
    Mit dieser Technik ist man dem Traum Logik, Inhalt und Layout zu trennen ein großes Stück weiter gekommen. Dennoch muss immer noch das zugrunde liegende HTML – welches von CSS in Form gebracht wird – irgendwo herkommen. Bei vielen dynamischen Webseiten wird es bei Bedarf mittels eines PHP-Skriptes generiert. Doch anstatt einfach “echo” für die Ausgabe zu verwenden, kann hier eine weitere Technologie eingesetzt werden, die einem dabei hilft Logik, Layout und Inhalt getrennt zu halten. Die Rede ist hier von Template-Engines. Das ist natürlich auch nichts neues und auch die Engine, die ich vorstellen möchte ist schon recht alt. Allerdings hat sich gezeigt, dass trotz dem Hype, der um XSLT als Traum, der in Erfüllung geht gemacht wurde, Template-Engines nach wie vor ihre Berechtigung haben.
    Vor allem dann, wenn es sich um die beste aller Template-Engines: patTemplate handelt! (Was wäre ich für ein mieser Autor, wenn ich nicht von dem was ich schreibe überzeugt wäre.) Von weitem betrachtet funktioniert patTemplate wie alle anderen Template-Engines: Der Rahmen des Zieldokumentes (meist HTML) wird als Template angelegt. Dieses enthält dann Dokumentfragmente (HTML-Schnipsel), Platzhalter und beliebig viele Untertemplates, die wiederum Fragmente, Platzhalter und Untertemplates enthalten können. Kontrolliert wird das alles von einem PHP-Skript, welches konkrete Inhalte an die Template-Engine (patTemplate) übergibt, die damit ihrerseits die Platzhalter mit Leben füllen kann.

    <patTemplate:tmpl name="itinerary">
    <!-- Template mit XML Tags -->
    <p>
        Nächster Halt <strong><patTemplate:var name="stop" /></strong>
        um <patTemplate:var name="eta" />
        (Verspätung <patTemplate:var name="delay" /> min).
    </p>
    </patTemplate:tmpl>
    
    <patTemplate:tmpl name="itinerary_next">
    <!-- Die Kurzform der Platzhalter gestaltet Templats lesbarer -->
    <p>
        Nächster Halt <strong>{STOP}</strong> um {ETA}
        (Verspätung {DALAY} min).
    </p>
    </patTemplate:tmpl>
    
    <?php
    $tmpl = new patTemplate();
    $tmpl->setRoot('template');
    $tmpl->readTeamplatesFromInput('itinerary_next.tmpl');
    $tmpl->addVar('itinerary_next', 'stop', 'Fulda');
    $tmpl->addVar('itinerary_next', 'eta', '2008-11-02 21:52:00');
    $tmpl->addVar('itinerary_next', 'delay', '7');
    $tmpl->displayParsedTemplate();
    ?>

    Die Template-Dateien selbst verwenden XML-Tags um Untertemplates, Platzhalter und Template-Funktionen auszuzeichnen. Auf diese Weise fügen sie sich nahtlos in HTML-Dokumente ein und machen das Erlernen von patTemplate-Tags für den geübten HTMLer zum Kinderspiel. Natürlich enthalten die Templates keinerlei Programmcode. Die gesamte Logik welche Inhalte dargestellt werden sollen ist in der PHP-Datei enthalten. Dennoch hat der HTMLer die Möglichkeit Logik in die Templates zu packen. Dies geschieht mit “condition”-Templates. Somit ist es dem HTMLer möglich die Darstellungslogik zu verändern, ohne dem PHPler in die Quere zu kommen – also ohne, dass Änderungen im PHP-Code notwendig wären.

    <patTemplate:tmpl name="itinerary">
    <!-- Die Kurzform der Platzhalter gestaltet Templats lesbarer -->
    <p>
        Nächster Halt <strong>{STOP}</strong> um {ETA}
        <patTemplate:tmpl type="condition" conditionvar="delay" varscope="__parent">
            <patTemplate:sub condition="0">
                <!-- keine Verspätung -->
            </patTemplate:sub>
            <patTemplate:sub condition="__default">
                (Verspätung {DALAY} min)
            </patTemplate:sub>
        </patTemplate:tmpl>
    </p>
    </patTemplate:tmpl>

    Zu den weiteren Grundelementen eines jeden Template-Systems sind wiederholbare Blöcke. Bei patTemplate werden dazu einfach Untertemplates verwendet, die so oft wiederholt werden, wie Datensätze vorhanden sind. Damit lassen sich ganz leicht Templates für Listen und Tabellen erstellen. Auch der PHPler muss im Grunde nichts neues Lernen, alles was er tun muss, ist diese Liste an patTemplate zu übergeben.

    <?php
    $tmpl = new patTemplate();
    $tmpl->readTemplatesFromInput('itinerary_list');
    
    $base   =   array(
            'start' => 'Frankfurt (Main) Hbf',
            'des'   => 'Dresden Hbf',
            'train' => 'ICE'
            'no'    => '1545'
        );
    
    $tmpl->addVars('reiseplan', $base);
    
    $list   =   array();
    $list[] =   array(
            'stop'  =>  'Frankfurt'
            'eta'   =>  '2008-10-29 17:20:00'
        );
    $list[] =   array(
            'stop'  =>  'Fulda'
            'eta'   =>  '2008-10-29 18:11:00'
        );
    $list[] =   array(
            'stop'  =>  'Eisenach
            'eta'   =>  '2008-10-29 18:59:00'
        );
    $list[] =   array(
            'stop'  =>  'Erefurt
            'eta'   =>  '2008-10-29 19:32:00'
        );
    
    $tmpl->addVar('list', $list);
    $tmpl->displayParsedTemplate();
    ?>
    
    <patTemplate:tmpl name="itinerary">
    <ol>
        <patTemplate:tmpl>
        <li>
            <strong>{STOP}</strong> {ETA}
        </li<
        </patTemplate:tmpl>
    </ol>
    </patTemplate:tmpl>

    Damit geht der Traum von der Trennung von Darstellung und Inhalt schon ein Stück weit in Erfüllung und kombiniert man dieses Werkzeug mit CSS kommt man schon sehr weit. Vorallem aber bleibt so der PHP- und HTML-Code sauber getrennt, was eine Voraussetzung für die Wartbarkeit ist.

    Die bis hier gezeigten Features beherrschen eigentlich allesTemplate-Engines – die meisten können noch viel mehr. PatTemplate natürlich auch. Um aber nicht den Rahmen zu sprengen und niemanden ins Land der Träume zu schicken möchte ich an dieser Stelle auf die umfangreichen Beispiele [1] verweisen.
    Ein mächtiges Feature möchte ich aber noch kurz vorstellen:
    Variablen-Modifier. In den bisher gezeigten Beispielen wurde die Ankunftszeit der Züge in dem Format ausgegeben wie es z.B. in der Datenbank gespeichert wird. Das ist für den Programmierer (PHPler) praktisch, aber für den Anwender wäre es besser die Uhrzeit in einem gängigeren Format auszugeben.

    Diese Anpassung ließe sich natürlich mit einem simplen Funktionsaufruf im PHP-Code bewerkstelligen, aber eigentlich handelt es doch um ein Problem der Darstellung und gehört ins Template. Ist damit der Traum von der Trennung von Code und Layout zerstört?
    Abhilfe für dieses Problem schafft der Variablen-Modifier Dateformat. Dieser ist in der Lage einen Zeitstempel wie gewünscht zu formatieren. Das gewünschte Format wird einfach als Attribute des XML-Tags übergeben. Natürlich ist der Modifier nichts weiter als eine Klasse, die ihrerseits die normalen PHP-Funktionen verwendet um die Uhrzeit zu formatieren. Der Vorteil besteht darin, dass der Funktionsaufruf aus dem Template heraus erfolgt. Schließlich ist das Format der Uhrzeit eine Sache der Darstellung und hat nichts mit der eigentlichen Programmlogik zu tun.

    <patTemplate:tmpl name="itinerary">
    <ol>
        <patTemplate:tmpl>
        <li>
            <strong>{STOP}</strong>
            <patTemplate:var name="eta" modifier="dateformat" format="%h:%m" />
        </li<
        </patTemplate:tmpl>
    </ol>
    </patTemplate:tmpl>

    Weitere Beispiele für Modifier die bereits mit patTemplate mitgeliefert werden sind Truncate (zum Abschneiden von Texten), Wordwrap (fügt Zeilenumbrüche ein) oder Numberformat (formatiert Zahlen). Werden spezielle Modifier benötigt, muss lediglich eine Klasse implementiert werden die von patTemplate_Modifier abgeleitet ist. Außerdem muss patTemplate mitgeteilt werden in welchem Verzeichnis die speziellen Modifier zu finden sind.
    Auf diese Weise kann patTemplate Variablen-Modifier aus beliebig vielen Verzeichnissen automatisch bei Bedarf nachladen. Übrigens ist es mit dem gleichen Mechanismus möglich alle patTemplate Module (wie InputFilter oder TemplateReader) zu erweitern oder zu ersetzen.
    Obwohl bestimmt noch einige Fragen offen bleiben und Template-Engines nicht der Weisheit letzter Schluss sind, geht der Traum von der Trennung von Inhalt, Layout und Logik zumindest teilweise in Erfüllung. Außerdem wir durch den Einsatz einer Template-Engine, insbesondere patTemplate viel leichter die die Programmlogik modular zu halten. Zumindest aber geht Nils Traum in Erfüllung: er hat nämlich einen Artikel über patTemplate für sein Blog bekommen.

    [0] PHP-Application-Tools Homepage
    [1] patTemplate Beispiele
    [2] Daily snapshots
    [3] patTemplate Trac

    11 Kommentare »


    • Alex
      am 11. November 2008 um 10:03 Uhr

      hmmm, interessant mal von einer Smarty-Alternative zu lesen. Aber wenn ich mir so die ausgedehnte Syntax anschaue, dann bleibe ich lieber wo ich bin ;)

      Aber gibt es eigentlich Template-Engines, die wirklich Logik vom Inhalt trennen? Also keine Conditions und auch keine Schleifen im Template? Wenn ich mir manchmal ein fertiges Smarty-Template anschaue, dann weiß ich nicht wo mehr Logik drinsteckt…


    • Nils Langner
      am 11. November 2008 um 10:58 Uhr

      Erstmal vielen Dank an Gerd für diesen Artikel. Bis jetzt habe ich leider nicht die Zeit gefunden, mich in patTemplate einzuarbeiten, da wir in den meisten Projekten smarty einsetzen. Ich denke aber, dass ich in der nächsten Zeit mal mit patTemplate rumspielen werde.

      Stimmt es eigentlich, dass Joomla auch mal auf pat aufgesetzt hat oder es vielleicht immer noch macht?


    • Ralf Eggert
      am 11. November 2008 um 11:13 Uhr

      @Alex

      was verstehst du unter Logik vom Inhalt trennen? Ich trenne zwischen Businesslogik und Präsentationslogik.

      Dass man in einem Template nicht auf Datenbank zugreifen soll und auch nicht die Währungskurse umrechnet ist ja klar. Nur wie willst du z.B. Listen ausgeben, wenn dein Template keine Präsentationslogik enthalten darf? Meine erste eigene Template Engine funktionierte in etwa so. Für das Ausgeben einer einfachen Tabelle hatte ich dann mehrere einzelne Frickeltemplates, die ineinander durch die Templateengine verschachtelt werden mussten. Die Präsentationslogik steckte dabei also nicht in den Templates selber, sondern in der Konfiguration. Ekelhafte Zeiten waren das damals… ;-)

      Heute bin ich froh, dass die Präsentationslogik durchaus seinen Einzug in die Templateengines gemacht hat. Nach den dunklen Zeiten, in denen ich Smarty eingesetzt habe, geht es bei mir aber wieder Back-to-the-Roots und ich verwendende einfach PHP als Template-Engine. So wie es das Zend Framework auch macht. Dann muss ich wenigstens keine Syntax wie Smarty oder patTemplate im Hinterkopf behalten.

      @Gerd

      Sehr schöner Artikel, der patTemplate gut zusammen fasst. Auch wenn es mich in meiner Überzeugung bestärkt, für neue Projekte wieder wie eben erwähnt für die Templates PHP einzusetzen.

      Gruss,

      Ralf


    • Salz`
      am 11. November 2008 um 11:43 Uhr

      Jepp, Joomla verwendet hier und dort patTemplate, bin ich selber schon drauf gestoßen. Bin mir aber gerade nicht sicher ob die aktuelle 1.5 das noch tut, halte mich selber von Joomla mittlerweile fern.


    • Nils Langner
      am 11. November 2008 um 11:52 Uhr

      Ich halte Template Engines eigentlich immer für hilfreich, sobald ein Webdesigner sich um das Layout kümmert. Die Syntax von pat ist immer doch einfacher zu lernen, als PHP selbst. Ein weiterer Benefit ist natürlich, dass sie gar nicht erst auf die Idee kommen, PHP Code in die Templates reinzupacken.


    • Alex
      am 11. November 2008 um 11:53 Uhr

      @Ralf
      Typo3-Templates besitzen keine echte Logik, also gehen tut es ja irgendwie.

      Ich weiß dass es gut und bequem ist, in die Templates Schleifen und Bedingungen einbauen zu können. Aber ich finde es suboptimal, dass man Templates mit Logik (Schleifen, Conditions, Modifiers, eigene Funktionen) vollpacken kann. Da denkst du als PHP-Entwickler, du hättest alles unter Kontrolle, dabei ist dir der Designer schon längst mit seinen Codes im Template durchgebrannt, weil er auf $POST,$GET und $SERVER zugreifen und eigene Variablen instanziieren kann. Das ist zu viel.

      Von daher frage ich mich, ob es als Alternative zu Smarty oder patTemplate sowas gibt und ob es überhaupt Sinn macht. Dieser Artikel bringt in mir Gefühle hoch…


    • gERD
      am 11. November 2008 um 15:30 Uhr

      Neben dem Ziel das Paradigma der Trennung zu verwirklichen, steht aber auch die Anwendbarkeit einer Lösung im Vordergrund. So ist es für mich besonders wichtig, dass die Templates wie HTML aussehen und die PHP-Skripte wie PHP. Damit kann eine echte Arbeitsteilung vollzogen werden: der HTML macht HTML, der PHPler macht PHP. Wird so gearbeitet, kristallisiert sich ziemlich schnell heraus welche Logik zur Darstellung und damit eigentlich ins Template gehört.

      Natürlich ist es oft so, dass sich der Programmierer um beide Seite kümmern muss. In diesem Fall empfehle ich die Trennung im “Geiste” zu vollführen, ansonsten wird der Programmierer schnell zu irgendwelchen Hacks verführt.

      Das ist meiner Meinung nach das was Joomla macht. Joomla verwendet intern patTemplate, allerdings werden die patTemplate-XML-Tags umbennant weshalb es nicht auf den ersten Blick zu erkennen ist.

      Hier noch ein altest Zitat aus dem Usenet (Bülent Caliskan in de.org.ccc): “Von der religiösen Sprengkraft her rangieren Newsreader gleich hinter Texteditoren und dem Weltuntergang.”


    • Ralf Eggert
      am 11. November 2008 um 15:56 Uhr

      Das wunderbare an der Sache ist ja, dass es viele Wege gibt, die nach Rom führen. Manche Wege sind lang und umständlich, andere ausgetreten, wieder andere steinig, und noch andere führen nach Bielefeld und nicht nach Rom… ;-)

      @Nils

      ich würde bei diesem Satz “Ich halte Template Engines eigentlich immer für hilfreich, sobald ein Webdesigner sich um das Layout kümmert.” das Wort Webdesigner austauschen. Für mich sollte ein Webdesigner schon ein wenig PHP können. Sonst ist es mehr ein Pixelschubser… ;-)


    • Sebastian
      am 11. November 2008 um 16:51 Uhr

      Hallo,

      also ich verwende SMARTY und bin recht zufrieden. Was mich aber sehr stört, dass man in den Templates häufig mehr Logik benutzen muss als im PHP-Sourcecode.

      Noch was eigentlich ist ein (Web)Designer nur einer der Layouts und Designs erstellt. Ein Coder, er erstellt die Layouts in HTML etc. “programmiert” die vom Designer designten Designs (was ein Ausdruck).
      Ein Progger (Programmier) programmiert in PHP etc.
      Falls ich Falsch liege korrigiert mich bitte.
      Grüße


    • Ulf
      am 11. November 2008 um 18:20 Uhr

      Gibts vielleicht bald noch einen Artikel zum Vergleich von patTemplate und Smarty? Ich habe mit beiden Engines schon gearbeitet und sehe keine allzu großen Unterschiede. Mich würde es aber sehr stark interessieren, irgendworin müssen sie sich ja unterscheiden. :)

      Und ich bin auch ausdrücklich ein Befürworter von Template-Engines. Ich finde schon dass ein heutiger Designer/Coder mehr als nur Photoshop kennen sollte, aber PHP gehört imo auch nicht dazu. Ich sehe vor allem die Gefahr, dass dann der Code nicht mehr so hochwertig ist als wie bei einer definierten Template-Syntax. Natürlich kann man auch mit Smarty direkt PHP coden, aber auch an dieser Stelle kann man Code Conventions einführen. Ein PHP5-Programmierer darf ja auch nicht 10 Objekte erzeugen, welche dann nie verwendet werden (ich hoffe zumindest das dies bei den meisten Projekten per Code Convention verboten ist ;) ).


    • Lukas
      am 11. November 2008 um 18:21 Uhr

      Ich verwende meine eigene Template-Klasse – und bin total zufrieden damit. PHP als Templatesprache ist immer noch die beste Wahl, wie ich finde.

    RSS Feed für Kommentare zu diesem Artikel. TrackBack URL

    Hinterlasse einen Kommentar

    Werbung
    PHP Magazin
    Ausgabe 02/2010

    Dieses Mal mit Artikeln zu den Themen OpenSocial und Apache Shindig, Graphentheorie, Smarty3

    t3n
    Ausgabe 19

    Social Media (R)evolution. Weitere Themen sind noSQL, Crowdsourcing ...

    PHP Journal
    Ausgabe 2/2010

    PHP & Windows optimal nutzen, die besten PHP-CMS im Überblick, Google-API mit Zend Framework nutzen.

    Wir wurden schon öfters gefragt, ob man uns nicht irgendwie unterstützen kann. Die Antwort war immer einfach: Klar! Am einfachsten ist es eure nächsten Einkäufe bei Amazon über unsere Link abzuwickeln. Damit würdet ihr uns schon sehr helfen. Über Co-Autoren freuen wir uns aber noch mehr.