Portal > Foren > Ankündigungen, News und Feedback > Tutorials > [PHP] Ein einfaches Template-System
Thema geschlossen
 
LinkBack Themen-Optionen Thema durchsuchen
Alt 09.10.2005, 18:30 Nach oben    #1
Lutz Mahlstedt
 
Benutzerbild von MrNiceGuy
 
Registriert seit: 14.08.2005
Ort: Nienburg / Weser
Beiträge: 827
Standard [PHP] Ein einfaches Template-System

So, in diesem Tutorial werde ich eine Möglichkeit vorstellen, wie man eine kleine, aber doch recht komplexe Template-Engine selber programmieren kann. Hierbei steht im Vordergrund den Code so kurz - und somit übersichtlich - wie möglich zu halten. Später soll es einem dann möglich sein, diese Klasse nach seinen Wünschen und Bedürfnissen umzuprogrammieren.

Als Grundlage nutze ich das Tutorial [PHP] OOP - eine Einführung.

Was soll uns diese Klasse bieten? Wir wollen eine kleine, aber doch schön erweiterbare Template-Engine programmieren. Wir benötigen also einen Speicherort für unsere Templates. Für die Lösung dieses Problems nutze ich ein Array in der Klasse, in der die Inhalte eines Templates gespeichert werden und bei einem erneuten Aufruf des selben Templates im weiteren Verlauf des Scriptes zu beschleunigen.
Ich will nicht für jeden Kleinkram eine extra Datei anlegen, in der dann nur 2 Bytes enthalten sind, sondern ich möchte sie in bestimmte Kategorien zusammenfassen, die als eine Art Container fungieren. Schließlich haben wir z.B. Templates, die wir nur fürs Gästebuch benötigen und welche, die nur für News zuständig sind, warum also nicht alle, die nur dafür verwendet werden in einer Template-Datei zusammenfassen?
Variablen sollen in den Templates selbstverständlich ersetzt werden durch die Inhalte der Variablen und es sollte möglich sein direkt in einem Template ein anderes Template ausgeben zu lassen.

Machen wir uns also an die Grundstruktur:

PHP-Code:
<?php
class template extends class_default
{
  var 
$cfg = array ('folder' => FALSE);

  var 
$data = array();

  
/* Hier kommen die Funktionen hinein */
}
?>
Voraussetzung hier ist natürlich die Initialisierung der Klasse class_default, die in obigem Tutorial (siehe Link) beschrieben wird.

Als Konfigurationsvariablen nutzen wir vorerst nur 'folder', das mit dem Wert FALSE gefüllt wird. Hier steht später der Ordner drin, in dem die Templates gesucht werden.
Die Variable $data wird zur Laufzeit die Inhalte der Templates enthalten.

Um sofort beim Instanziieren einen Ordner zuzuweisen müssen wir einen Konstruktor (http://de2.php.net/manual/de/languag...onstructor.php) definieren:

PHP-Code:
<?php
/* nachfolgend der Code für die Klasse template */

  
function template ($folder)
  {
    
$this->config ('folder'$folder);
  }

/* nachfolgender Code */
?>
Nun muss die Instanz der Template-Klasse den Pfad mit angeben, aus dem die Templates geladen werden sollen:

PHP-Code:
<?php
/* template definieren */

$tmpl = new template ('./tmpl/');
?>
Für das Handling der Templates sehe ich nun 3 Funktionen vor:

tmpl_load () - Lädt einen Template-Container (eine Template-Datei); Einzelne Templates werden rausgefiltert und separat in der Klasse gespeichert
tmpl_get () - Lädt ein Template aus dem angegebenen Container; Zum Laden des Containers wird vorab tmpl_load () ausgeführt
tmpl_parse () - Wandelt Platzhalter im Template um

Gehen wir von Oben nach Unten vor und fangen mit dem Sinnigsten selbst an: Dem Laden eines Containers.

PHP-Code:
<?php
/* nachfolgend der Code für die Klasse template */

  
function tmpl_load ($container)
  {
    if (
$this->config ('folder') !== FALSE)
    {
      
/* Die Variable 'folder' wurde gesetzt */
      
$container_ucase strtoupper ($container);

      if (isset (
$this->data[$container_ucase]) === TRUE)
      {
        
/* Der Container wurde bereits geladen */
        
return TRUE;
      }
      else
      {
        
/* Der Container wurde noch nicht geladen */
        
$this->data[$container_ucase] = array ();

        
$tmpl_file $this->config ('folder').$container.'.tmpl';

        if (
is_file ($tmpl_file))
        {
          
/* Container-Datei existiert */

          /* Laden der Container-Datei in $tmpl */
          
$tmpl_data implode (''file ($tmpl_file));

          if (empty (
$tmpl_data) === FALSE)
          {
            
/* Container-Datei war nicht leer */

            /* An dieser Stelle werden die einzelnen Templates extrahiert und gespeichert */
          
}
          return 
TRUE;
        }
        else
        {
          
/* Container-Datei existiert nicht */
          
return FALSE;
        }
      }
    }
    else
    {
      
/* Die Variable 'folder' wurde nicht gesetzt */
      
return FALSE;
    }
  }

/* nachfolgender Code */
?>
Bisher speichert diese Funktion noch keine Daten, aber lädt zumindest - sofern der Ordner angegeben ist und die Datei vorhanden ist - den Inhalt der Container-Datei in eine temporäre Variable, aus der später die einzelnen Templates extrahiert werden. Dies geschieht wie folgt:

PHP-Code:
<?php
/* nachfolgend der Code für die Klasse template */

            
preg_match_all ('/(?:<!-- BEGIN )([\w]{1,})(?: -->)(.*?)(?:<!-- END -->)/is'$tmpl_data$data);
            foreach (
$data[1] AS $key => $val)
            {
              
$this->data[$container_ucase][strtoupper ($val)] = $data[2][$key];
            }

/* nachfolgender Code */
?>
Hier wird mittels RegEx nach Konstruktionen gesucht, die im Template-Container wie folgt aussehen:

Code:
<!-- BEGIN test_template1 -->
Dies ist das erste Template in diesem Container
<!-- END -->

<!-- BEGIN test_template2 -->
Und dies ist das 2. Template.
<!-- END -->
Gespeichert wird alles im mehrdimensionalen Array $data. Damit später auch bei unterschiedlicher Schreibweise (gemeint ist hier Groß- und Kleinschreibung) das richtige Template geladen wird, werden die Keys mit strtoupper () vorher in Großbuchstaben umgewandelt. Die erste Dimension des Arrays enthält also den Namen des Containers und die 2. Dimension den Namen des Templates aus dem Container.

Es kann also auch im Gästebuch durchaus noch auf die Templates des Containers 'news' zugegriffen werden, sollte dies notwendig sein. Aber die Hierarchie und Aufteilung der Templates bleibt ja jedem selbst überlassen :)

Wir können nun also Template-Container direkt in die Klasse laden lassen. Der manuelle Funktionsaufruf macht jedoch wenig Sinn, da diese Funktion bei jeder Anwendung von tmpl_get ohnehin gestartet wird.

Kommen wir nun zur Funktion tmpl_get (), welche beim Erfolg den Inhalt des Templates zurückgeben soll (ohne vorher die Platzhalter ersetzt zu haben) oder im Fehlerfall FALSE zurückgibt:

PHP-Code:
<?php
/* nachfolgend der Code für die Klasse template */

  
function tmpl_get ($container$tmpl)
  {
    if (
$this->tmpl_load ($container) === TRUE)
    {
      
$container strtoupper ($container);
      
$tmpl      strtoupper ($tmpl);

      if (isset (
$this->data[$container][$tmpl]) === TRUE)
      {
        return 
$this->data[$container][$tmpl];
      }
      else
      {
        return 
FALSE;
      }
    }
    else
    {
      return 
FALSE;
    }
  }

/* nachfolgender Code */
?>
Diese Funktion ist recht simpel, wie man sieht, hat dafür auch wenig, was sie leistet: Sie gibt entweder das Template zurück - falls vorhanden - oder FALSE.

Etwas komplizierter ist da schon die Funktion tmpl_parse (), die mit Abstand am Meisten zu tun haben wird, da hier die Platzhalter ersetzt werden.

PHP-Code:
<?php
/* nachfolgend der Code für die Klasse template */

  
function tmpl_parse ($container$tmpl)
  {
    
$template $this->tmpl_get ($container$tmpl);
    if (
$template !== FALSE)
    {
      
/* Hier kommt die Abarbeitung des Templates rein */
    
}
    else
    {
      
$return FALSE;
    }

    return 
$return;
  }

/* nachfolgender Code */
?>
Sollte das Template nicht geladen werden können, gibt die Funktion FALSE zurück. Ansonsten wird das Template geparsed. Hierfür benötigen wir ein Array, dass die mittels global geladenen Variablen speichert, um sie nur ein einziges Mal laden zu müssen. Dies ist nötig, damit innerhalb dieser Funktion auf die Variablen zugegriffen werden kann. Außerdem soll eine Schleife durchlaufen werden, solange es eine Veränderung am Quellcode gibt, um Rekursionen abzufangen, die durch in Variablen enthaltenen Template-Code oder eingefügte Templates entstehen können.

Mittels eines preg_match_all () werden alle möglichen Template-Codes rausgesucht. Möglich sind hierbei Codes in der Form {TMPL:container:template} um ein weiteres Template oder {VAR:variable} um den Wert von $variable an dieser Stelle einzufügen. Die RegEx sind extra etwas einfachr gehalten, um die Funktionsweise ansich zu erklären, hierbei wird ein zugriff auf Instanzvariablen unter Anderem nicht berücksichtigt. Die Änderungen, die vorgenommen wreden sollen, werden in einem Array $replace gespeichert und nach Abarbeitung der gefundenen Template-Codes auf das Template ausgeführt. Dies wiederholt sich so lange, bis keine Änderung des Inhaltes von $templates mehr erfolgt.
PHP-Code:
<?php
      $vars_loaded 
= array ();

      unset (
$temp);

      while (
$temp != $template)
      {
        
$temp $template;

        
$match = array ('(TMPL)\:(\w+)\:(\w+)',
                        
'(VAR)\:(\w+)'
                        
);
        
preg_match_all ('/\{(?:'.implode (')|(?:'$match).')\}/'$template$data);
        if (
count ($data[0]) > 0)
        {
          unset (
$replace);
          for (
$i 0;
          
$i count ($data[0]);
          
$i++)
          {
            
$replace['from'][$i] = $data[0][$i];
            
$replace['to'][$i] = '';

            if (
$data[4][$i] == 'VAR')
            {
              if (
$vars_loaded[$data[5][$i]] !== TRUE)
              {
                
$vars_loaded[$data[5][$i]] = TRUE;
                global ${
$data[5][$i]};
              }

              
$replace['to'][$i] = ${$data[5][$i]};
            }
            elseif (
$data[1][$i] == 'TMPL')
            {
              
$replace['to'][$i] = $this->tmpl_get ($data[2][$i], $data[3][$i]);
            }
          }
        }
        
$template str_replace ($replace['from'], $replace['to'], $template);
      }
      
$return $template;
?>
Damit ist die Funktion tmpl_parse () auch schon abgeschlossen. Man kann diese Funktion natürlich um weitere Template-Codes erweitern, wobei sich dann ein SWITCH zur Lokalisierung der einzelnen Codes anbieten würde.

Wir schließen also die Klasse nun ab und fügen noch die Initialisierung in der Variablen $tmpl durch.
PHP-Code:
<?php
}

$tmpl = new template ('./tmpl/');
?>
Damit haben wir die Template-Klasse also in $tmpl stehen. Als kleines Beispiel sollte nun folgendes reichen:

PHP-Code:
<?php
/* Hier die Klasse initialisieren und instanziieren */

$hello 'Hallo';
$world 'Welt!';

echo 
$tmpl->tmpl_parse ('example''hello_world');
?>
erzeugt mit folgendem Template im Container 'example.tmpl':
Code:
<!-- BEGIN hello_world -->
{TMPL:example:hello} {TMPL:example:world}
<!-- END -->

<!-- BEGIN hello -->
{VAR:hello}
<!-- END -->

<!-- BEGIN world -->
{VAR:world}
<!-- END -->
folgende Ausgabe am Browser: "Hallo Welt!". Zugegeben: Ein sehr schwawchsinniges Template, aber ich wollte nochmal verdeutlichen, wie genau nun die Template-Codes im Template selber angewandt werden.

Ich hoffe, dass trotz der Länge des Tutorials und der Schreibweise gut rübergekommen ist, wie man Templates recht einfach nutzen kann. Vielleicht fällt dem Einen oder Anderen ja eine Möglichkeit ein, effizient mit dieser Klasse zu arbeiten, indem er sie seinen Wünschen und Belangen entsprechend Anpasst. Zu wünsche wäre es jedenfalls :)

MfG
MrNiceGuy

Geändert von Jann Hendrik (28.05.2008 um 19:58 Uhr) Grund: link aktualisiert
MrNiceGuy ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Thema geschlossen

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
indireckte Frage zu Template system kampfgnom PHP-Programmierung 4 04.06.2007 04:12
eigenes Template System mit Sprachunterstützung jjelliss PHP-Programmierung 61 15.09.2006 10:00
Template System Jan Gesuche 8 01.07.2006 23:27
Kleines Prob mit phpBB Template System Garnele PEAR, PECL und Frameworks 6 22.10.2005 00:31


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:55 Uhr.


Powered by vBulletin® Version 3.8.4 (Deutsch)
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47