heinetz: Templates verschachteln

Hallo Forum,

ich bin gerade dabei ein koplexes Projekt und dessen Aufbau zu überdenken.
Das ganze ist, wie folgt aus includes aufgebaut. Die Logik funktioniert, aber ich möchte sie auf den Prüfstand stellen und über alterative Ansätze nachdenken. Aufgebaut ist das ganze prnzipiell, wie folgt:

index.php
-----------------------
include "config.inc.php";
include "values.inc.php";
include "main.inc.php";

<html>
 <body>
  <div id="header"><?=$header_str;?></div>
  <div id="content"><?=$content_str;?></div>
  <div id="footer"><?=$footer_str;?></div>
 </body>
</html>

values.php
-----------------------
$values = array(
 "header_val" = "Überschrift",
 "content_val" = "Inhalt",
 "footer_val" = "Fussnote");

include "header.inc.php
include "content.inc.php";
include "footer.inc.php";

z.B. content.inc.php
-----------------------
$content_str = "<span class="layout">".$values['content_val']."</span>";

Das funktioniert soweit. Was mir daran nicht gefällt, ist zum Einen, dass mir zuviel html in der index.php steht, die ja eigentlich ein Template ist und dass in den anderen Templates Variablen definiert und belegt werden.

Wie baut ihr soetwas (ohne Extra- Template-Engine) auf?

beste gruesse,
heinetz

  1. Hello,

    ein Template ist nach meinem Verständnis erst einmal eine Darstellungsvorschrift, die _ohne_ Daten daherkommt, sondern nur mit Platzhaltern für diese.

    Und speziell im PHP-Umfeld trenne ich dann zwischen aktiven und passiven Templates.

    Aktive sind solche, die eigene PHP-Sequenzen enthalten und somit vom PHP-Parser direkt ausgewertet werden können. Solche Templates kann ich deshalb nicht (oder nur unter Sicherheitsrisiken) von Anwendern erstellen lassen.

    Passive Templates würde nur HTML und Platzhalter enthalten. Diese Platzhalter würden dann durch eine spezielle Funktion durch ihre Inhalte ersetzt werden, notfalls solange, bis keine Platzhalter mehr vorhanden sind. Das würde bedeuten, dass die Funktion entweder sirekt Werte einsetzt für den Platzhalter, oder aber ihn expandiert, also durch andere Platzhalter (auch nebst Werten) ersetzt.

    Diese Ersetzung funktioniert in PHP bestens mit der Funktion str_(i)replace(), wenn es sich um festgelegte Platzhalter handelt. Wenn man den Platzhaltern nun auch noch wieder Funktionlität zuordnen möchte, dann ist sicherlich ein preg_replace() (in einer Schleife) die bessere Wahl.

    Bei str_replace() benötigt man übrigens bei passender Vorbereitung keine Schleife für die stufenweise Substitution, da diese durch das Abarbeiten des Erstzungsarrays schon quasi-rekursiv arbeitet.

    ein paar Gedanken dazu findest Du auch im Archiv:
    http://forum.de.selfhtml.org/archiv/2009/5/t186387/#m1237998
    http://forum.de.selfhtml.org/archiv/2008/8/t175925/#m1159112

    Das Archiv ist voll von Gedanken zu Templates und Template-Engines. Du solltest es also auch nochmal selber durchsuchen.

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
    1. hello,

      das ist fetter Stoff! Allein Deine beiden Verweise reichen mir, um den Ansatz mal zu verfolgen:

      index.php
      --------------------------------------------

      <?php  
      //Werte die in den Templates eingesetzt werden  
      $page['header'] = "Überschrift";  
      $page['content'] = "Inhalt";  
      $page['footer'] = "Fussnote";  
        
      $pattern = '#<!--\{([A-Z]+):(.*)\}-->#';  
      $template = file_get_contents('page.tpl');  
        
      function parse_callback ($match){  
       switch ($match[1]){  
        case "TEMPLATE":  
        global $pattern;  
        return preg_replace_callback($pattern, "parse_callback", file_get_contents($match[2]);  
        break;  
        
        case "STRING":  
        global $page;  
        return $page[$match[2]];  
        break;  
       }  
      }  
        
      echo preg_replace_callback($pattern, "parse_callback", $template);  
      ?>
      

      page.tpl
      --------------------------------------------
      <html>
       <body>
        <div id="header"><!--{STRING:headline}--></div>
        <div id="content"><!--{TEMPLATE:body.tpl}--></div>
        <div id="footer"><!--{STRING:footer}--></div>
       </body>
      </html>

      body.tpl
      --------------------------------------------
      <span class="body"><!--{STRING:content}--></span>

      Das ist, wenn ich Dich richtig verstanden habe, der Ansatz mit rein passiven Templates. Ist das richtig?

      beste gruesse,
      heinetz

      1. Hello,

        das ist fetter Stoff! Allein Deine beiden Verweise reichen mir, um den Ansatz mal zu verfolgen:

        index.php

        <?php

        //Werte die in den Templates eingesetzt werden
        $page['header'] = "Überschrift";
        $page['content'] = "Inhalt";
        $page['footer'] = "Fussnote";

        $pattern = '#<!--{([A-Z]+):(.*)}-->#';
        $template = file_get_contents('page.tpl');

        function parse_callback ($match){
        switch ($match[1]){
          case "TEMPLATE":
          global $pattern;
          return preg_replace_callback($pattern, "parse_callback", file_get_contents($match[2]);
          break;

        case "STRING":
          global $page;
          return $page[$match[2]];
          break;
        }
        }

        echo preg_replace_callback($pattern, "parse_callback", $template);
        ?>

        
        >   
        >   
        > page.tpl  
        > --------------------------------------------  
        > <html>  
        >  <body>  
        >   <div id="header"><!--{STRING:headline}--></div>  
        >   <div id="content"><!--{TEMPLATE:body.tpl}--></div>  
        >   <div id="footer"><!--{STRING:footer}--></div>  
        >  </body>  
        > </html>  
        >   
        >   
        > body.tpl  
        > --------------------------------------------  
        > <span class="body"><!--{STRING:content}--></span>  
        >   
        >   
        > Das ist, wenn ich Dich richtig verstanden habe, der Ansatz mit rein passiven Templates. Ist das richtig?  
          
        Das sieht schon gut aus.  
          
        Das Denkproblem bei diesem Lösungsweg bleibt die Datenkopplung mit Listen.  
        Man will dann ja ggf. ein Teiltemplate solange wiederholen, wie Daten vorhanden sind.  
        Und bei langen Listen will man dann auch noch ein "Paging" haben...  
          
        Das in passive Templates einzubauen, geht ggf. aber über die Rekursion, die Du ja schon abgebildet hast. Die müsste dann noch begrenzt werden durch einen entsprechenden Zähler...  
          
          
          
          
        Liebe Grüße aus dem schönen Oberharz  
          
          
        Tom vom Berg  
        ![](http://selfhtml.bitworks.de/Virencheck.gif)  
          
        
        -- 
         ☻\_  
        /▌  
        / \ Nur selber lernen macht schlau  
        <http://bergpost.annerschbarrich.de>
        
        1. Hi,

          Das sieht schon gut aus.

          Das freut mich!

          Das Denkproblem bei diesem Lösungsweg bleibt die Datenkopplung mit Listen.
          Man will dann ja ggf. ein Teiltemplate solange wiederholen, wie Daten vorhanden sind.
          Und bei langen Listen will man dann auch noch ein "Paging" haben...

          Das in passive Templates einzubauen, geht ggf. aber über die Rekursion, die Du ja schon abgebildet hast. Die müsste dann noch begrenzt werden durch einen entsprechenden Zähler...

          Ok, verstehe. Da sind sicher verschiedene Wege denkbar. Eine Liste könnte über einen Loop ein Codefragment wiederholen. Interessieren würde mich, wann und wie aktive Templates zum Einsatz kommen würden.

          beste gruesse,
          heinetz

          1. Hello,

            Das in passive Templates einzubauen, geht ggf. aber über die Rekursion, die Du ja schon abgebildet hast. Die müsste dann noch begrenzt werden durch einen entsprechenden Zähler...

            Ok, verstehe. Da sind sicher verschiedene Wege denkbar. Eine Liste könnte über einen Loop ein Codefragment wiederholen. Interessieren würde mich, wann und wie aktive Templates zum Einsatz kommen würden.

            "Aktive Templates" sollten in einem vernünftigen CMS nur im internen Gebrauch bentutzt werden, so dass kein (auch authorisierter) User sie jemals manipulieren könnte, sondern nur der Programmverantwortliche.

            Aber wenn Du dein System mit den passiven Templates weiter so engagiert verfolgst, kann ich mir vorstellen, dass Du überhaupt keine aktiven Templates mehr benötigst, sondern nur noch ein paar gute Methoden schreiben musst für die Verarbeitung von Daten und passiven Templates.

            Diese ganzen Klamotten mit eval() und unkontrollierten include()s gehören mMn nämlich schon lange auf den Schrotthaufen der Zeit.

            Include() sollte sich auf Programmstruktur beschränken und die Finger von der Darstellung lassen. Diese sollte immer isoliert eingelesen werden, damit sie niemals die Programm-Kontrolle erlangen kann.

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. Hi,

              Ok, verstehe. Da sind sicher verschiedene Wege denkbar. Eine Liste könnte über einen Loop ein Codefragment wiederholen. Interessieren würde mich, wann und wie aktive Templates zum Einsatz kommen würden.

              "Aktive Templates" sollten in einem vernünftigen CMS nur im internen Gebrauch bentutzt werden, so dass kein (auch authorisierter) User sie jemals manipulieren könnte, sondern nur der Programmverantwortliche.

              Genau so hatte ich Deinen Ansatz verstanden ...

              Aber wenn Du dein System mit den passiven Templates weiter so engagiert verfolgst, kann ich mir vorstellen, dass Du überhaupt keine aktiven Templates mehr benötigst, sondern nur noch ein paar gute Methoden schreiben musst für die Verarbeitung von Daten und passiven Templates.

              ... genau das kann ich mir eben auch vorstellen und daher rührt die Frage, in welchem Fall ein "Aktives Template" notwendig wird, bzw. aus welchen Gründen man darauf ausweicht.

              beste gruesse,
              heinetz

              1. Hello,

                Aber wenn Du dein System mit den passiven Templates weiter so engagiert verfolgst, kann ich mir vorstellen, dass Du überhaupt keine aktiven Templates mehr benötigst, sondern nur noch ein paar gute Methoden schreiben musst für die Verarbeitung von Daten und passiven Templates.

                ... genau das kann ich mir eben auch vorstellen und daher rührt die Frage, in welchem Fall ein "Aktives Template" notwendig wird, bzw. aus welchen Gründen man darauf ausweicht.

                Soweit ich das überschauen kann, eigentlich nur aus Bequemlichkeit. Die Möglichkeiten sind eben bereits vorhanden, wenn man sein PHP auspackt. Man muss nicht erst nachdenken, sondern kann gelich loshacken. Dass das nicht besonders klug ist, wissen wir aber :-O

                Wenn ich ein _System_ benötige/haben will, dass durch Usereingaben oder Daten gesteuert werden soll, muss ich auch konsequent eins aufbauen und kann dann nicht einfach mittendrin aufhören und doch wieder auf die verwendete Programmiersprache zurückgreifen. Dieser Rückfall wären dann die berühmten includes() oder die wilden Konstruktionen mit eval().

                Die passiven Templates haben den Vorteil, dass nichts passieren kann, was du nicht vorgesehen hast. Sie kosten den Server i.d.R. allerdings auch etwas mehr Kraft. Das kann man dann durch ein intelligentes Caching aber wieder ausgleichen. Geschachtelte Templates, die sich (längere Zeit, für mehrere Dutzend Requests) nicht verändern, werden dabei einfach expandiert und diese  Teilergebnisse werden abgespeichert, ggf. unter Beibehaltung der Platzhalter für Daten.
                Das ergibt dann bei Arrays besondere Anforderungen.

                Und wenn Du diesen Denkansatz verfolgst, kommst Du irgendwann darauf, dass Du eigentlich auch einen kleinen Generator für Templates benötigst, der Dir Listentemplates automatisch erzeugt (unter Beibehaltung von [modifizierten] Paltzhaltern für die Daten) und erst am Ende die Daten einstanzt.

                Du solltest in Deinem Funktionspark also daran denken, die Templateauswertung so zu gestalten, dass ein fertiges Endergebnis abgespeichert werden kann, zum Debugging der Pfad mitgeschrieben werden kann und das Ergebnis sowohl netto (also ohne Daten) als auch brutto (also komplett mit den eingesetzten Daten) erzeugt werden kann.

                Es sollte also möglich sein, ein leeres "Formular" (also nur HTML ohne Nutzdaten) im Browser anzeigen lassen zu können.

                Liebe Grüße aus dem schönen Oberharz

                Tom vom Berg

                --
                 ☻_
                /▌
                / \ Nur selber lernen macht schlau
                http://bergpost.annerschbarrich.de
                1. Hallo Tom,

                  Soweit ich das überschauen kann, eigentlich nur aus Bequemlichkeit. Die Möglichkeiten sind eben bereits vorhanden, wenn man sein PHP auspackt. Man muss nicht erst nachdenken, sondern kann gelich loshacken. Dass das nicht besonders klug ist, wissen wir aber :-O

                  Tausend Dank für die Lektion. Ich habe einiges gelernt, kenne jetzt die Richtung in die ich will und weiss sogar warum ;) Ich bin geneigt, die Geschichte weiterzuspinnen und als Konsequenz aus dem Verstandenen die nächste Baustelle aufzureissen, die aus meiner Sicht noch einen Schritt vorher kommt: OOP

                  Ich muss es leider lassen und statt dessen für die Zukunft planen ;(

                  Hintergrund ist der, dass ich vor einem komplexen Internetprojekt mit selbstgestricktem CMS stehe, dass eigentlich aus meiner Sicht ganz schön aufgebaut ist, weil ich mit meinen includes und config-Files schon einen recht modularen Ansatz verfolgt hatte, als ich es vor einigen Jahren aufgebaut hatte. Jetzt habe ich die Freigabe für ein Modul, das in seinem Umfang so gross ist, dass ich mich umsehen wollte was ich bei der Gelegenheit mal umbauen kann. Für eine Baustelle konnte ich mir die Zeit nehmen und habe die Verzeichnisstruktur grundlegend geändert. Um den Templategedanken konsequent zu verfolgen, muss ich aus meiner Sicht OOP begreifen, was ich dringend will, was aber zuviel Zeit kostet, um der Sache in diesem Moment nachzugehen.

                  danke für die Geduld und

                  beste gruesse,
                  heinetz

  2. Hallo Heinetz,
    arbeite gerade auch an einem Template-System, vieleicht interessant für dich: http://forum.de.selfhtml.org/?t=202536&m=1368082

    Gruß Andreas

  3. Hallo,

    index.php

      
      
    ob_start();  
    if($_GET["bla"] == "blo") {  
     include ("blo.php");  
     $title = "BLO";  
    } elseif ($_GET["bla"] == "bli") {  
     include ("somethingelse.php");  
     $title = "BLI";  
    }  
    $content = ob_get_clean();  
    include ("html_frame.inc.php");  
      
    
    

    html_frame.inc.php

      
    <h1><?=$title</h1>  
    <div class="content">  
    <?=$content?>  
    </div>  
    
    

    Ps. Es macht eine Menge Sinn, sich mal anzuschauen, wie das Zend-Framework diese Dinge behandelt, inclusive Coding-Standard. Falls man "richtiges PHP" lernen will und nicht nur seinem Spieltrieb und seiner Erkundungs- und Entdeckungsfreude gepaart mit Erfindergeist freien Lauf lassen will. Es gelingt sowieso nicht, das Rad neu zu erfinden. Wobei ich schon verstehen kann, dass die Selbstbastelei viel Spaß macht. Ist ja so ein bisschen wie Modelbau oder sonstwelches Hobby.

    Gruß

    jobo

    1. hi,

      Ps. Es macht eine Menge Sinn, sich mal anzuschauen, wie das Zend-Framework diese Dinge behandelt, inclusive Coding-Standard. Falls man "richtiges PHP" lernen will und nicht nur seinem Spieltrieb und seiner Erkundungs- und Entdeckungsfreude gepaart mit Erfindergeist freien Lauf lassen will. Es gelingt sowieso nicht, das Rad neu zu erfinden. Wobei ich schon verstehen kann, dass die Selbstbastelei viel Spaß macht. Ist ja so ein bisschen wie Modelbau oder sonstwelches Hobby.

      ich sehe das (mittlerweile) auch so, dass man das Rad nicht neu erfinden muss und auf bewährtes zurückgreifen sollte ABER ich muss immernoch bis zu einem bestimmten Punkt verstehen, was das bewährte im Prinzip macht, bevor ich mich gut dabei fühle, es einzusetzen.

      gruss,
      heinetz

      1. Hello,

        Wobei ich schon verstehen kann, dass die Selbstbastelei viel Spaß macht. Ist ja so ein bisschen wie Modelbau oder sonstwelches Hobby.

        Das entscheidung den Wissenschaftler vom Techniker. Der Techniker sollte keine Skrupel haben, Dinge einfach nachzumachen und Vorhandenes zu verwenden. Der Wissenschaftler hat eher den Anspruch, sein Gedankengebäude Stein auf Stein zu errichten, damit es in jeder Situation nachvollziehbar bleibt.

        Bei eigenen Entwicklungen sollte man mMn also ruhig bis zu einem gewissen Grad empirisch arbeiten und nicht wie beim Modellbau nur nachbauen. Wenn man dann dabei Dinge "erfindet", die es schon lange gibt, ist das allerdings gleichzeitig Bestätigung und Ernüchterung :-)

        Aber die Nuancen machen oft die neue Anwendbarkeit einer Erfindung aus, auf die man aber selten kommt, wenn man immer nur alles nachmacht.

        Wie aber die hiesige Diskussion zum Thema "Template-Systeme" zeigt, ist es vorab erst notwendig, genau festzulegen, was man darunter überhaupt verstehen will, welches die Zielsetzung sein soll.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Hello,

          Häh? Wieder man-in-the-middle am Werk?

          sollte heißen:

          Das unterscheidet den Wissenschaftler vom Techniker.

          Liebe Grüße aus dem schönen Oberharz

          Tom vom Berg

          --
           ☻_
          /▌
          / \ Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de