2. Die eigene Template-Klasse
2.1. Theorie
Dieses Kapitel beschäftigt sich mit der Entwicklung einer eigenen Template-
Klasse.
Hier werden noch mal einige Konzepte, die dieses Semester in der Vorlesung
besprochen wurden, angewendet. So brauchen wir zum Beispiel Funktionen,
Klassen und Regular Expressions.
Fangen wir an, das, was wir in den letzten Kapiteln gelernt haben, zu nutzen,
und daraus eine eigene Klasse zu schreiben.
Was brauchen wir, um die Klasse nutzen zu können? Als Erstes sicherlich eine
Funktion, um die Variablen in eine Liste oder ein Array zu schreiben.
Code:
assign(varname, value);
Als Nächstes brauchen wir natürlich auch eine Funktion, damit die Datei
gelesen und angezeigt werden kann:
Soweit die Memberfunktionen, die wir schon beim Nutzen der Klasse
gebraucht haben. Jetzt kommen allerdings noch ein paar weitere dazu, die
wir für das Parsen des Templatefiles brauchen.
Code:
parseFile($string); // liest das File und gibt es zurück
replaceVar($ref); // ersetzt Variablen im String
replaceArray($ref); // ersetzt Arrays im String
replaceForeach($ref); // ersetzt foreach-Schleifen im String
… diese Liste könnte jetzt endlos fortgeführt werden, um alle
Sprachkonstrukte zu ersetzten. Weitere Möglichkeiten wären die
IF-Bedingung, While-Schleifen, Objekt-Ersetzungen u.s.w.
Damit unser Beispiel übersichtlich bleibt, sollten wir es allerdings bei den drei
Ersetzungen lassen.
2.2. Klassendiagramm
Hier nochmals eine grafische Darstellung der Template-Klasse. Vielleicht
kommen einige mit dieser Darstellung besser klar.
2.3. Funktion der Memberfunktionen
Jetzt geht es los. Die Syntax, wie die Klassen erstellt werden, erinnert sehr
an Java und dürfte kein Problem darstellen:
PHP-Code:
class Template {
private $var;
public function assign($var, $value){
...
}
...
}
Da wir jetzt die Struktur das Klasse haben, können wir anfangen die Funktion
zu implementieren.
2.3.1. assign()
Als Erstes, würde ich vorschlagen, bauen wir die „assign“-Funktion, um die
Variablen zu registrieren.
Diese lässt sich sehr einfach debuggen und wir brauchen keine zusätzliche
Funktionalität der Klasse für die ersten Tests.
Um die Variablen zu speichern, legen wir noch eine Membervariable an,
welche als Array die Werte und Namen abspeichert.
PHP-Code:
private $varList = NULL;
Jetzt können wir die Variablen auch schon in das Array schreiben. Das
einfache Handling der Arrays unter PHP nimmt uns eine Menge Arbeit ab.
PHP-Code:
public function assign($name, $value){
$this->varList[$name] = $value;
}
Natürlich könnte man jetzt noch Fehler abfangen und schauen, ob der
Variablenname schon einmal registriert wurde, aber für unser Beispiel soll das
genügen.
Mit dem Array $varList können wir jetzt auf alle Werte zugreifen.
Die Funktion können wir testen. Legen wir ein Objekt der Klasse an und lassen
und das gesamte Array zurückgeben.
Achtung, die Sichtbarkeit muss für dieses Beispiel auf „public“ gesetzt
werden, da man sonst nicht auf die Variable zugreifen kann.
Beispiel:
PHP-Code:
class Template {
public $varList = NULL;
public function assign($name, $value){
$this->varList[$name] = $value;
}
}
$tmpl = new Template();
$tmpl->assign(eins,"Hallo");
$tmpl->assign(zwei,"Welt");
echo "<pre>";
print_r($tmpl->varList);
echo "</pre>";
2.3.2. display()
Diese Funktion wird genutzt, um das Template-File zu öffnen und den String
zum Parsen weiterzuleiten.
Wir müssen testen, ob die Datei überhaupt existiert und ob sie gelesen
werden kann.
Wenn dies der Fall ist, können wir die Datei parsen und via echo an den Client
schicken.
PHP-Code:
public function display($tpl){
if ((!file_exists($this->template_dir . "/" . $tpl)) OR
!is_readable($this->template_dir . "/" . $tpl)) {
die("Can not read the File");
}
$string = file_get_contents($this->template_dir . "/" .
$tpl);
echo $this->parseFile($string);
}
2.3.3. setTemplateDir() und endlich der Konstruktor
Wer die Funktion display() aufmerksam studiert hat, wird festgestellt haben,
dass die Variable „this->template_dir“ bisher verwendet, aber noch nicht
angelegt wurde.
Das holen wir schnell noch nach und damit wir die Variable „private“
schreiben können, bauen wir gleich noch eine Funktion, um das Verzeichnis
zu setzen.
PHP-Code:
public function setTemplateDir($dir = NULL){
// hier wird eine default-Wert an die Funktion übergeben,
wenn kein Argument angegeben wird
if (is_null($dir)) {
$this->template_dir = dirname(__FILE__);
}
else{
$this->template_dir = $dir;
}
}
Sehr clever ist es hier, diese Funktion gleich im Kostruktor einzubinden, da
sie in jedem Fall aufgerufen werden muss.
PHP-Code:
public function Template($dir = NULL){
$this->setTemplateDir($dir);
}
Leider wird ein Überladen von Funktionen in PHP nicht unterstützt. Mit dem
Trick, einer Funktion einen Default-Wert zu übergeben, lässt sich allerdings
so manches Problem lösen
Template($dir = NULL).
2.3.4. parseFile($string)
In der Funktion „
display()“ wurde bereit
„
parseFile($string)“ aufgerufen.
Hier wird nichts anderes gemacht, als den Dateistring aus der Template-Datei
zu untersuchen und die Platzhalter zu ersetzten.
Klingt schwierig? Ist es auch.
Aber auch das werden wir verstehen und schon bald werden wir dieses
Konzept zu schätzen wissen.
Als Erstes müssen wir uns wieder an Regular Expressions erinnern.
Da wir einen String nach bestimmten, formatierten Tokens untersuchen
wollen, ist es am einfachsten, diese mit RegEx_Mustern zu „parsen“.
Wie wollten wir den Platzhalter einer Variablen definieren?
Es steht immer ein „
{$“ am Anfang und ein „
}“ am Ende.
Dazwischen stehen Buchstaben beliebiger Reihenfolge und Länge.
Ich habe mal ein Pattern vorbereitet, der uns wahrscheinlich schon
weiter hilft: (danke Stuck Mojo und
St@eff.en)
Code:
$pattern = '%\{\$(\w+)\}%';
Ich denke, das Suchmuster müsste allen klar sein? Warum die Klammer ()
gebraucht wird, erkläre ich weiter unten.
So, jetzt kommen wir zu dem eigentlichem Ersetzten des Platzhalters. Dazu
nutzen wir die Funktion preg_replace_callback.
PHP-Code:
$string = preg_replace_callback($pattern, array(&$this, 'replaceVar'), $string);
Was diese genau tun, werde ich im nächsten Abschnitt versuchen zu
erläutern. Auf jeden Fall ersetzt diese unseren Platzhalter im String mit dem
Wert aus der Variablenliste. Sie sucht uns sozusagen zur Laufzeit den
gesuchten Ersetzungswert.
2.3.4.1.Die PHP-Funktion preg_replace_callback()
In der Hilfe auf
www.php.net ist die folgende Beschreibung der Funktion zu
finden:
Zitat:
“Sucht und ersetzt einen regulären Ausdruck unter Verwendung eines Callbacks.
PHP-Code:
mixed preg_replace_callback ( mixed Suchmuster, callback Callback,
mixed Zeichenkette [, int Limit] );
Abgesehen von der Tatsache, dass statt des Parameters Ersatz ein Callback
angeben werden soll, dem ein Array von Übereinstimmungen mit der
durchsuchten Zeichenkette übergeben wird, ist das Verhalten dieser
Funktion identisch zu preg_replace(). Der Callback sollte die Ersetzungs-
Zeichenkette liefern.“ (http://www.php.net/manual/de/functio...e-callback.php)
|
Da es nicht auf Anhieb klar ist, was das bedeutet, versuche ich es noch
einmal, etwas anders zu erklären.
Der Funktion wird ein Suchmuster übergeben sowie die Zeichenkette, in der
gesucht werden soll.
Soweit sollte das alles von
preg_replace() bekannt sein. Aber der zweite
Parameter ist etwas, dass hier bestimmt neu erscheint.
Mit ihm kann eine Funktion angegeben werden, die aufgerufen wird um den
„
replace“-Wert zurückzugeben. Die Funktion bekommt dabei (automatisch)
den mit dem Suchmuster gefundenen Ausdruck als Argument übergeben.
Dieses Argument – welches der Funktion übergeben wird – setzt sich dabei
wie folgt zusammen:
Die Übergabe ist immer ein Array, in welchem der gesamte Ausdruck im ersten
Element (
$arr[0]) gespeichert wird.
In den weiteren Elementen (
$arr[1] .. $arr[n]) werden jeweils die Inhalte
in den gefundenen Klammern () zurückgegeben.
Jetzt sollte auch klar sein, warum in dem Suchmuster
'%\{\$(\w+)\}%'
der Teil in dem der Variablenname gefunden wird, noch einmal in Klammern
steht.
Jetzt habe ich sicher einige total verwirrt. Aber betrachten wir das einmal an
einem Beispiel.
Wir haben einen String mit der Variable
{$varname}. Dieser wird natürlich
durch unser Pattern gefunden. Wie schaut dann dass Array – welches ja der
Funktion als Argument übergeben wird – aus?
Bsp. 1
Code:
'%\{\$(\w+)\}%'
$arr[0] = {$varname}
$arr[1] = varname
Bsp. 2
Code:
'%{foreach from=\$(\w+) item=(\w+)}(.*){/foreach}%sU';
$arr[0]= {foreach from=$varame item=name}<html-
Tags>{/foreach}
$arr[1] = varname
$arr[2] = }<html-Tags>
Nun wird mit Sicherheit deutlich, dass das wir in der Callback-Funktion den
Wert
$arr[1] nutzen können um in der Variablenliste unseren gesuchten Wert
zu finden.
Dieser wird dann im String durch preg_replace_callback ersetzt.
Das sollten wir jetzt erstmal setzten lassen, aber wenn wir das verstanden
haben, ist der Rest der Klasse (fast) kein Problem mehr.
2.3.5. replaceVar()
Da wir jetzt wissen, dass eine Funktion die Werte zum Ersetzen der
Platzhalter im String zurückgibt, müssen wir diese jetzt auch implementieren.
[php]private function replaceVar($ref){
return $this->varList[$ref[1]];
}
[/PHP
Hier wird noch mal deutlich, dass die Funktion nur den Wert des Keys,
welcher als Argument übergeben wurde, zurückgeben wird.
2.3.6. weitere Funktionen
Weiter oben haben wir eine Reihe weiterer Funktionen benannt, welche in
einer Template-Klasse implementiert sein sollten.
Diese alle hier zu besprechen, wäre ein zu großer Aufwand. Da das Prinzip bei
allen weiteren Ersetzungen immer gleich ist, sollte es aber möglich sein, die
Klasse nach und nach zu erweitern.
An der Hochschule haben wir uns im Praktikum weiter mit dieser Klasse beschäftigt.
Gut, das war es eigentlich vom mir. Ich hoffe ich habe bis hier noch nicht alle
Leute verlohren und es hat ein wenig Spaß gemacht
Die Praktikas zu SMARTY sowie das PDF zur Vorlesung könnt Ihr Euch hier downloaden:
Nico Lange -> Publikationen