Eigenes Template-System

Sephcom

Mitglied
Schönen guten Tag.
Ich würde gerne ein eigenes Template-System schreiben, hab aber so wirklich noch keinen Ansatz gefunden.

Und zwar habe ich (vereinfacht) eine HTML (TPL) Datei.
In dieser ist der Platzhalter {content}

In PHP habe ich nun eine Function "output"

Diese soll {content} ersetzen.

Wenn ich nun aber merhmals output untereinander schreibe, soll der TExt auch untereinander stehen...


Bsp:
PHP:
output('Hallo');

Ergibt
Hallo

schreibe ich nun
PHP:
output('Hallo');
output('Welt');

soll es so ausgegeben Werden

Hallo
Welt

Oder vielleicht sogar mit bbcodes,
also

PHP:
output('Hallo\nWelt');

Hallo
Welt

Wie kann ich das realisieren?
 
Hab da noch ein kleines Tutorial auf meiner Festplatte liegen, das ich mal veröffentlichen sollte. Damit solltest du mal einen Start für deinen Parser haben

PHP three tier architecture

Datenlayer
Als ersts brauchen wir ein bisschen Code, der uns Daten zur Verfügung stellt. Hier mal was ganz einfaches
AgentInfo.inc
PHP:
<?php
class AgentInfo{
    public $ip;
    private $host;
    public $refer;
    public function __construct(){
        $this->ip = getenv(REMOTE_ADDR);
        $this->host = gethostbyaddr($this->ip);
        $this->refer=getenv(HTTP_REFERER);
    }
    public function getHost(){
        return $this->host;
    }
}
?>

Simpel und als Klass natürlich so nur beschränkt sinnvoll. Doch darum gehts jetzt nicht. Die Datenlogik haben wir jetzt also zusammen.



Applikationslayer
Um diesen Layer sauber zu gestallten, verwendet man meist ein Templatesystem. In diesem Fall mach ich selber einen kleinen Parser. den stell ich dann in den Businesslayer. Als Platzhalter denk ich mir etwas aus, dass so nicht so schnell wieder auftaucht.
{%varible%} soll als Platzhalter dienen

tmpl.client.html
HTML:
<html>
    <head>
        <title>Three Tier Architekture</title>
    </head>
    <body>
        Willkommen zu diesem kleinen Test.
        <br />Du kommst von {%refer%}.
        <br />und {%host%} ist dein Host über den du im www surfst.
        <br />Deine IP ist {%ip%}
    </body>
</html>

Natürlich kann an das noch mit CSS und allem drumm und drann ausschmücken.
Doch wie kommen jetzt die Inhalte unserer Klasse clsclient in dieses Template?
Dazu schreib ich mal kurz einen kleinen Parser. Dieser gehört zum Templatesyste. Normalerweise nimmt man etwas komplexeres, dass ein wenig mehr kann als nur Variablen ersetzen. Doch für dieses Beispiel reicht es aus.

parse.inc
PHP:
<?php
function parse($vars, $templateName)
{
    // Falls $vars nur eine Variable ist und nicht ein Array
    if (!is_array($vars)) $vars=array($vars);     
    reset($vars);

    // Template öffnen
    $file=fopen($templateName,"r");            
    // Template einlesen      
    $tmpl=fread($file,filesize($templateName));
    fclose($file);

    // Template parsen
    while (list ($key, $value) = each ($vars)){
        $tmpl=str_replace('{%'.$key.'%}',$value,$tmpl);   
    }
    // geparstes Template als String zurückgeben.
    return $tmpl;                                  
}
?>

Businesslayer
Genau. Dieser Layer verbindet alles miteinander. Er nimmt die Infos aus dem Datalayer, nimmt den Parser und das Template und schreibt am schluss mit einem einzigen Echo-Befehl die Ganze Seite.

site.php
PHP:
<?php
    // Parser einbinden
    include_once('parse.inc');
    // Datalayer einbinden
    include_once('AgentInfo.inc');
    // eine Instanz des Dataobject initzialisieren
    $agentInfo = new AgentInfo();
    
    // Variablen zum Parsen vorbereiten (wir übergeben alle Variablen als Array)
    $vars=array(
        'ip'        =>  $agentInfo->ip,
        'refer'     =>  $agentInfo->refer,
        'host'      =>  $agentInfo->getHost(),
    );
    
    // Template parsen und ausgeben
    echo parse($vars, 'tmpl.client.html');
?>

So einfach ist das.
Der Businesslayer in einem Komplexeren Projekt, ist eigentlich nichts anderes als eine Datei, die nur noch Zuordnungen macht.

WEITERE AUSSICHTEN
Tja, wozu ist es eigentlich nützue, dass an die Daten so universell macht? Nehmen wir mal ein Gästebuch. Die Datalogik ist immer dieselelbe. Nur das Layout will man anpassen. Dann ist es in diesem Fall genau eine Datei, die man mit HTML anpassen kann. Einfach und übersichtlich.
Oder man will eine Seite mit verschiedenen Skins erstellen. Nix einfacher als das. Dubliziere die Templates und mache im Businesslayer eine Templateselektion hinein, dass er das richtige Template abholt... finish ist der Zauber.

LINKS
vLib
Dieses Templatesystem verwende ich. ist einfach zu handhaben und beitet sehr viel Möglichekeiten und besitzt eine hervorragende deutsche Dokumentation.
 
Zuletzt bearbeitet:
Das ist leider nicht das, was ich meine...

Sagen wir mal, wir haben eine template.tpl (vereinfacht)
PHP:
<html>
<head>
<title><?=$title?></title>
</head>
<body>
<?=$content?>
</body>
</html>

Nun die functions.php
PHP:
<?php
function output($text){
    // Hier soll ein Code rein, der $content durch $text ersetzt
}
?>

So das bekomme ich soweit hin
nun die index.php
PHP:
<?php
require_once 'functions.php';
output('Hallo');
?>

nun wird also "hallo" ausgegeben

Ich möchte nun aber, der übersichtlichkeit zu gunsten, dass ich so oft output schreiben kann, wie ich möchte.

Weil sobald ich ja einmal output($text) geschrieben habe, wird der $content teil überschrieben.
d.h. wenn ich ein zweites mal output($text) schreibe, wird das ignoriert.
 
Okay habs jetzt gelöst :D

Habs mit arrays und foreach schleifen gemacht.

Also...die template.tpl
PHP:
<html> 
<head> 
<title><?=$title?></title> 
</head> 
<body> 
<?=$content?> 
</body> 
</html>

dann die functions.php
PHP:
$output = array();

function output($text){
	global $output;
	global $oc;
	$oc+=1;
	$output[$oc]=$text;
}
function footer(){
	global $output;
	foreach($output as $add){
		$content=$content.'<br />'.$add;
	}
    require_once 'templates/template.tpl';
}

So...und nun die index.php

PHP:
<?php

require_once 'functions.php';

output('Hallo');
output('Wie gehts?');
footer();

?>

So klappts ^^ also das original von mir sieht noch leicht anders aus, aber das ist der ansatz, also wenn jmd vor der gleichen frage steht, bitteschön :D

Weil ganz ehrlich...eine Template Engine ala Smarty ist unnötig. Pseudo-Code die angeblich alles einfacher machen sollen, aber durch verschachtelungen und so weiter das Template nur noch schwieriger aussehen lassen.
 
Zuletzt bearbeitet:
Nun, was du da machst ist etwas ähnliches wie mein parser (funktion parse) aus meinem Beispiel. Du arbeitest mit dem global-Befehl. Davon kann ich dir nur abraten. Wenn dein Code komplexer wird, weisst du auf einmal nicht mehr, wo überan an der variable $output herumgebastelt hast.

Auch ist dein " template" eine einfache PHP-Seite und kein Template.

Doch nun noch Tipps zu deinem Code, da du es ja gerne klein und fein haben willst.

item: wozu on output() das oc? $output[]=$text; bewirkt dasselbe. Dann kannst du dir deine Funktion output gleich sparen.
item: die Funktion footer() kannst du durch den Befehl imlode() ersetzen
ergo: functions.php brauchst du nicht

index.php
PHP:
<?php
    $output[] = 'Hallo';
    $output[] = 'Wie gehts?';
    
    $content = implode('<br />', $output);

    require_once 'templates/template.tpl'
?>
 
Zurück