PHPTAL PHP Template Attribute Language Laurent Bedubourg Kornel Lesinski Dan Sheppard Anton Andriyevskyy Axel Zo:llich Versionsgeschichte ---------------------------------------------------------------------- Inhaltsverzeichnis 1. Einleitung 2. Warum PHPTAL? 3. Installation 4. Ein erstes Beispiel 5. Die >>Template Attribute Language<< 1. Attributrangfolge 2. TAL-Namensraum 1. tal:define 2. tal:condition 3. tal:repeat 4. tal:omit-tag 5. tal:replace 6. tal:content 7. tal:attributes 1. Optionale Attribute 8. tal:on-error 3. METAL Namensraum 1. metal:define-macro 2. metal:use-macro 3. metal:define-slot 4. metal:fill-slot 4. I18N Namensraum 1. i18n:translate 2. i18n:attributes 3. i18n:name 4. XHTML in U:bersetzungen 5. PHPTAL Namensraum 1. phptal:debug 2. phptal:cache 1. Gesteuerte Auffrischung 2. Begrenzungen: 3. phptal:tales 6. tal:block 7. PHPTALES 1. path: 2. Bedingte Anweisungen 3. string: 4. php: 5. not: 6. exists: 7. default 8. structure 9. Ausdrucksketten 6. PHP Integration 1. Konstanten 2. Konfigurationsmethoden 3. class PHPTAL 4. interface PHPTAL_Filter 5. interface PHPTAL_Trigger 6. interface PHPTAL_TranslationService 1. method setLanguage(...) 2. method useDomain($domain) 3. method setVar($key,$value) 4. method translate($key) 7. Die Arbeit mit gettext 1. Erzeugung der U:bersetzungsverzeichnisstruktur (Hmpf) 2. Portable Object files 3. Translation Domain 4. PHP usage in PHPTAL 5. Variable interpolation 8. Massgeschneiderte Operatoren entwickeln 7. Hinweis fu:r Systembetreuer 8. Nu:tzliche Verweise 9. Danksagungen Einleitung ---------------------------------------------------------------------- PHPTAL ist eine Implementierung des hervorragenden >>Zope Page Template<<- (ZPT-)Systems in PHP. PHPTAL unterstu:tzt die TAL-, METAL- und I18N-Namensra:ume. PHPTALES ist das A:quivalent zu TALES, der >>Template Attribute Language Expression Syntax<<. Es legt fest, wie XML-Attributwerte behandelt werden. Da PHPTALES TALES sehr stark a:hnelt, sollte es leicht sein, Python-TAL- Vorlagen in solche fu:r PHP beziehungsweise andersherum zu u:bertragen. Um TAL-konform zu sein, implementiert PHPTAL einen XPath-artigen Datenzugriff. PHPTAL ist unter der LGPL frei verfu:gbar; es wurde von Laurent Bedubourg entwickelt und wird von Kornel Lesinski betreut. Warum PHPTAL? ---------------------------------------------------------------------- Wir benutzen XML-/HTML-Vorlagen (>>Templates<<), um Logik (weshalb wird was ausgegeben) und Darstellung (wie sieht es im Brauser aus) voneinander zu trennen. Diese Trennung hat mehr als einen Vorteil: o besseres Anwendungsdesign o Umstrukturierungen werden einfacher o bessere Wartbarkeit o das Design la:sst sich leicht a:ndern Die meisten Vorlagensysteme (>>Template-Systeme<<) nutzen -, <% %>- oder -Auszeichnugen, um die Stellen zu finden, die verarbeitet werden mu:ssen. Dadurch wird die Entwicklung des Vorlagensystems einfacher, dem (Vorlagen-)designer wird die Arbeit aber unno:tig erschwert. TAL versteckt seine Logik gro:sstenteils in XML-Attributen und erha:lt dabei die Syntax und Struktur von XHTML. Dadurch ist ein direkte Betrachtung von TAL-Vorlagen in Brausern mo:glich (WYSIWYG-Editoren, unmittelbare Vorschau). Die HTML-Syntax-Hervorhebung (>>Syntax Highlighting<<) im Editor wird nicht gesto:rt. Falls Sie schon einmal mit einem einfachen Vorlagensystem gearbeitet haben, werden Ihnen bereits Codeschnipsel begegnet sein, die ungefa:hr wie folgt aussehen: <%loop myarray as myitem %> <%/loop%>
<% myitem %>
Mit PHPTAL ko:nnen Sie das folgendermassen schreiben:
text replaced by the item value sample 1 sample 2 sample 3
Der obige Code wird samt der enthaltenen Beispieldaten in einem normalen Brauser angezeigt werden, das heisst, dass Sie die Seite Ihren Kunden zeigen ko:nnen, ohne dass auch nur eine Zeile des Codes, der das Feld myarray erzeugt, schon existieren muss. Ein weitere grosser Vorteil von PHPTAL ist, dass Sie von der mehr als 3-ja:hrigen Erfahrung, der Dokumentation und der Hilfe der Zope-Gemeinschaft profitieren. PHPTAL verla:sst sich auf diese Gemeinschaft, um seinen Nutzern eine grosse Menge nu:tzlicher Informationen zu bieten. PHPTAL ist so aufgebaut, dass es fu:r fortgeschrittene Entwickler und anspruchsvolle (d.h. ressourcenintensive) Systeme so anpassbar wie mo:glich ist, aber dennoch fu:r den Anfa:nger durch bequeme und einfache Grundeinstellungen benutzbar bleibt (sogar ich habe es ausprobiert :). Installation ---------------------------------------------------------------------- PHPTAL wird als PEAR-Paket verteilt (siehe http://pear.php.net). Sie ko:nnen die PHPTAL-Bibliothek aber auch von der PHPTAL-Webseite (http://phptal.motion-twin.com) herunterladen. So installieren Sie PHPTAL via pear: pear install http://phptal.motion-twin.com/latest.tar.gz Einmal installiert, ko:nnen Sie PHPTAL via PEAR leicht auf aktuellem Stand halten: pear upgrade http://phptal.motion-twin.com/latest.tar.gz Nutzen Sie PEAR nicht, oder ist es auf ihrem Rechner nicht installiert, ko:nnen Sie auf das komprimierte Archiv ausweichen: tar zxvf PHPTAL-X.X.X.tar.gz cp -r PHPTAL-X.X.X/PHPTAL* /path/to/your/lib/folder Damit wird die Datei PHPTAL.php und der zugeho:rige PHPTAL-Ordner in /path/to/your/lib/folder installiert. Ein erstes Beispiel ---------------------------------------------------------------------- Um einen ersten Eindruck von PHPTAL zu gewinnen, hier ein einfaches Beispiel statt vieler Worte. Ihre Vorlage ist ein gu:ltiges XML-/HTML-Dokument (samt Wurzelelement). Die Datei nennen wir 'my_template_file.xhtml': Platz fu:r den Seitentitel

Beispieltitel

Name Telefonnummer
Name der Person Telefonnummer der Person
Beispielname Beispielnummer
Beispielname Beispielnummer
In php mu:ssen Sie lediglich die PHPTAL-Bibliothek einbinden und eventuell eine Variable anpassen, um ihre Vorlage zu individualisieren. name = $name; $this->phone = $phone; } } // let's create an array of objects for test purpose $people = array(); $people[] = new Person("bla", "0162/4578930"); $people[] = new Person("blabla", "0714/87629"); $people[] = new Person("blubb", "0102/6637912"); $people[] = new Person("blablubb", "0190/123456"); // put some data into the template context $template->title = 'Der Titeltext'; $template->people = $people; // execute the template try { echo $template->execute(); } catch (Exception $e){ echo $e; } ?> Wenn sie das PHP Script ausfu:hren, werden sie etwas a:hnlich dem Folgenden erhalten. Der Titeltext

Der Titeltext

Name Telefonnummer
bla 0162/4578930
blabla 0714/87629
blubb 0102/663791
blablubb 0190/123456
PHPTAL schert sich nicht besonders um Zeilenumbru:che und Einru:ckungen in den Dateien, die es liest bzw. erzeugt. Mo:chten Sie, dass der erzeugte HTML-Code hu:bsch wird, d.h mit Zeilenumbru:chen und perfekten Einru:ckungen, mu:ssen Sie ihn eventuell mit HTML Tidy nachbearbeiten. Die >>Template Attribute Language<< ---------------------------------------------------------------------- Inhaltsverzeichnis 1. Attributrangfolge 2. TAL-Namensraum 1. tal:define 2. tal:condition 3. tal:repeat 4. tal:omit-tag 5. tal:replace 6. tal:content 7. tal:attributes 1. Optionale Attribute 8. tal:on-error 3. METAL Namensraum 1. metal:define-macro 2. metal:use-macro 3. metal:define-slot 4. metal:fill-slot 4. I18N Namensraum 1. i18n:translate 2. i18n:attributes 3. i18n:name 4. XHTML in U:bersetzungen 5. PHPTAL Namensraum 1. phptal:debug 2. phptal:cache 1. Gesteuerte Auffrischung 2. Begrenzungen: 3. phptal:tales 6. tal:block 7. PHPTALES 1. path: 2. Bedingte Anweisungen 3. string: 4. php: 5. not: 6. exists: 7. default 8. structure 9. Ausdrucksketten >>Template Attribute Language<< (TAL) bedeutet ungefa:hr soviel wie attributbasierte Vorlagensprache. Dieser Abschnitt beschreibt TAL und seine Erweiterungen. Er zielt hauptsa:chlich auf Template-Designer ab, sollte aber auch von PHP-Programmierern gelesen werden. Attributrangfolge Es ist wichtig zu wissen, dass die Reihenfolge der TAL-Attribute innerhalb einer Auszeichnung bedeutungslos ist. Zum Beispiel ist ... genau dasselbe wie: ... Die PHPTAL-Rangfolge enspricht der in der TAL-Beschreibung festgelegten Abarbeitungsreihenfolge: 1. define 2. condition 3. repeat 4. content oder replace 5. attributes 6. omit-tag TAL-Namensraum 1. tal:define 2. tal:condition 3. tal:repeat 4. tal:omit-tag 5. tal:replace 6. tal:content 7. tal:attributes 1. Optionale Attribute 8. tal:on-error tal:define Dieses Attribut definiert eine oder mehrere Variablen, die im weiteren Verlauf in der Vorlage verwendet werden ko:nnen. Definition eines Ku:rzels fu:r einen langen Pfad: Definition einer Zeichenkette innerhalb einer Vorlage: Mehrere Variablen zugleich definieren: Definition einer Zeichenkette, die eine weitere Variable entha:lt: Ein kleiner Trick, der Ausgabepuffer benutzt: Hallo ${fname}, willkommen auf dieser Seite Sie ko:nnen tal:define auch zusammen mit anderen Attributen verwenden; es wird vor allen anderen ausgewertet. In obigen Beispielen wird die >>span<<-Auszeichnung in der Ausgabe nicht auftauchen, da sie weder druckbaren Inhalt noch Attribute entha:lt. Selbst die Meldung im letzten Beispiel wird nicht erscheinen. Sie wird von der Variablen hello geschluckt. Andererseits wird durch sowohl die Variable hello gesetzt, als auch der Text ausgegeben. Der folgende Code aber ist nicht erlaubt, da tal:define der Variable >>hello<< den Inhalt des Knotens zuweist. Der Inhalt des Knotens ist allerdings zu diesem Zeitpunkt noch unklar, da tal:content ihn erst spa:ter festlegt. Der tatsa:chliche Inhalt wird dabei wie Beispielinhalt ignoriert. hello wird nicht definiert und Sie erhalten eine Fehlermeldung. Hallo ${fname}, willkommen auf dieser Seite In den letzten Beispielen werden Sie ab und an u:ber das Schlu:sselwort 'global' vor einigen Variablennamen gestolpert sein. Variablen ko:nnen in PHPTAL entweder lokal oder global definiert werden. Eine globale Variable ist in allen XML-Knoten ihrer Vorlage oder aufgerufenen Makros sichtbar.

Im Gegensatz dazu ist eine lokale Variable nur innerhalb der Auszeichnung, in der Sie definiert ist, sichtbar.

Dieser Code liefert einen 'undefined variable' Fehler. tal:condition Das Element und sein Inhalt werden nur angezeigt, wenn das Ergebnis der Bedingung wahr ist. Welcome member ... Please login before accessing this page Wenn ihr PHP Unterbau ihrer Vorlage nicht genu:gend Methoden zu Verfu:gung stellt, werden Sie des o:fteren auf PHP zuru:ckgreifen mu:ssen, um spezielle Bedingungen zu pru:fen: ... Dadurch kann unerwu:nscht viel Logik in der Vorlage landen. Manchmal ist es daher besser der Vorlage boolsche Ausdru:cke oder Methoden anzubieten. ... ... tal:repeat Dieses Attribut arbeitet auf abza:hlbaren Objekten wie Feldern, assoziativen Feldern oder Objekten, die die PHP Iterator Klasse implementiert. Das tal:repeat Attribut wiederholt seine Auszeichnung und seinen Inhalt solange, bis es am Ende der angegebenen Quelle (Feld, Objekt) angekommen ist. text replaced by item Innerhalb einer solchen Schleife ko:nnen Sie mit speziellen repeat/* Pfaden auf aktuelle Schleifenzusta:nde (und die ihrer Eltern fu:r verschachtelte Schleifen) zugreifen. In obigen Beispiel liefert o repeat/item/key : den Elementenschlu:ssel, wenn some/result eine assoziative Quelle ist (sonst den Index) o repeat/item/index : den Elementenindex (0 bis Gesamtanzahl-1) o repeat/item/number : die Elementennummer (1 bis Gesamtanzahl) o repeat/item/even : wahr, wenn der Index des Elementes gerade ist o repeat/item/odd : wahr, wenn der Index des Elementes ungerade ist o repeat/item/start : wahr, wenn das Element das erste ist o repeat/item/end : wahr, wenn das Element das letzte ist o repeat/item/length : die Anzahl der Elemente in some/result item ist die Variable, die im tal:repeat Ausdruck definiert wird. tal:repeat wird in den meisten Fa:llen auf das Ergebnis einer SQL Datenbankabfrage angewendet werden. Der folgende Code funktioniert wenn playersRanking ein Objekt entha:lt, das das PHP Iterator Interface implementiert:
Position Player Score
tal:omit-tag Dieses Attribut gibt dem PHPTAL Parser auf, die Anfangs- und Endauszeichnung des umgebenden Elementes zu ignorieren und nur den Inhalt auszugeben. if the condition is true, then only this text will appear and span open and close will be removed Ergibt: only this text will appear, span open and close will be removed Dieses Attribut ist nu:tzlich, wenn Sie ein Auszeichnung wahlweise darstellen mo:chten oder nicht. Z.B. kann ein Text in Abha:ngigkeit von einer Bedingung einmal als Text und einmal als Verweis ausgezeichnet werden. Wenn Sie ein Element beno:tigen, das niemals ausgegeben wird, ko:nnen Sie dazu tal:block verwenden only this text will appear, ten times. tal:replace Dieses Attribut ersetzt die gesamte Auszeichnung durch den angegebenen Wert, oder durch nichts, wenn kein Wert agegeben wird. this ugly string and span Ergibt: this beautiful string tal:replace kann auch verwendet werden und Beispiele in Vorlagen zu schreiben die in der endgu:ltigen Ausgabe nicht enhalten sein sollen.
item value
sample 1
sample 2
tal:content Dieses Attribut ersetzt den Auszeichnungsinhalt durch das Ergebnis des enthaltenen Ausdrucks. will be replaced Ergibt: my string tal:attributes Mit tal:attributes ko:nnen HTML Attribute gesetzt, oder vera:ndert werden. sample link With a 'somelink' having: $somelink->href = "http://www.google.com"; $somelink->title = "google search engine"; $somelink->text = "the google search engine"; Ergibt: the google search engine Das Semikolon (;) trennt einzelne Attribute. Mo:chten Sie ein Semikolon ausgeben, so mu:ssen Sie es verdoppeln (;;). Ein etwas komplexeres Beispiel zu tal:repeat: ... Der php: Operator wird spa:ter genauer erkla:rt werden. Hier wird, wenn die Zeilennummer ungerade ist, tr ein class Attribut mit 'odd' als Wert zugewiesen sonst wird kein class Attribut gesetzt. "condition ? then : else" ist ein normales PHP Konstrukt, dass vorsichtig verwendet werden muss, sich aber in mehr als einer Situation als nu:tzlich erweist. Ein besserer Weg um dasselbe Ergebnis zu erhalten ist es, denn PHP Programmierer um einen massgeschneiderten Operator zu bitten (siehe PHP Integration / massgeschneiderte Operatoren), der dann wie folgt genutzt wird: ... Der Operator wird "odd" zuru:ckgeben, wenn repeat/ranking/odd wahr ist sonst 'false'. Optionale Attribute Verwenden Sie in tal:attributes TALES Alternativen (die a|b|c Notation) und ist nothing (oder NULL in PHP) die letzte der Alternativen, wird das Attribut garnicht ausgegeben wenn kein Wert dafu:r vorhanden ist. (Hierdurch werden leere Attribute vermieden.): ... tal:attributes="title object/tooltip | nothing"> XHTML Attribute wie selected, checked, usw. werden automatisch richtig verwendet. Beachten Sie, dass XHTML Gross- und Kleinschreibung unterscheidet. SELECTED ist in XHTML ein Fehler. Verwenden Sie selected. tal:on-error Wenn ein Pfadfehler oder irgendeine PHP Ausnahme in der Auszeichnug auftritt, ersetzt dieses Attribut die Auszeichnung durch das Ergebnis des tal:on-error Ausdrucks. the user name here Tritt beim Zugriff auf name oder user ein Fehler auf, wird die Fehlermeldung anstelle der Auszeichnung ausgegeben. Dies funktioniert auch bei mehreren Vorlagenebenen: METAL Namensraum 1. metal:define-macro 2. metal:use-macro 3. metal:define-slot 4. metal:fill-slot METAL ist die Kurzform fu:r "Macro Extension for TAL". Dieser durch PHPTAL unterstu:tzte Namensraum, erlaubt es Vorlagendesignern XML/XHTML Makros zu definieren und aufzurufen. metal:define-macro Dieses Attribut deklariert ein Makro. Makros lassen sich als eine Art Bibliothek aus kleinen Vorlagen verstehen, die in anderen Vorlagen wiederverwendet werden ko:nnen.

Last modified: page modification date
Makros erben den Variablenkontext des Aufrufers. In obigem Beispiel ha:ngt die Variable "mdate" von der aufrufenden Vorlage ab. metal:use-macro Dieses Attribut ruft ein Makro auf und setzt das Ergebnis an seiner statt in die akutelle Vorlage ein. Makros lassen sich u:ber deren Dateiname auch aus externen Vorlagen ansprechen. Der PHPTAL Ersetzungsmechanismus la:sst sich auch innerhalb von metal:use-macro Werten nutzen: Ein Makro darf sich selbst aufrufen. Auf diese Weise ko:nnen Sie Felder rekursiv ausgeben:
metal:define-slot Dieses Attribut darf nur innerhalb einer Auszeichnung mit metal:define-macro auftreten. Slots ko:nnen von der aufrufenden Vorlage mit, auch dynamisch generiertem, eigenem XML/XHTML Inhalt gefu:llt werden. Slots ko:nnen als eine Art ru:ckwirkende Einfu:gungen gesehen werden; ein Makro kann eine ganze Seite bilden, die durch Slots in Abha:ngigkeit vom URL individualisiert wird.
news description
Obiges Beispiel definiert eine Stelle 'news_place' die durch die aufrufende Vorlage u:berschrieben werden kann. Im na:chsten Abschnitt wird dieses Beispiel fortgefu:hrt. metal:fill-slot Dieses Attribut darf nur innerhalb eines metal:use-macro Blocks verwendet werden. Hiermit wird PHPTAL mitgeteilt einen bestimmten slot mit dem Inhalt innerhalb der metal:fill-slot Auszeichnung zu ersetzen.

user menu

Slots ermo:glichen durch ein einfaches Einsetzverfahren tatsa:chlich wiederverwendbare und individualisierbare Vorlagen. I18N Namensraum 1. i18n:translate 2. i18n:attributes 3. i18n:name 4. XHTML in U:bersetzungen "i18n" ist eine Kurzform fu:r das englische 'internationalization' (i, 18 Buchstaben, n). This Namensraum allow template designers to specify some text zones that must be translated during template evaluation. i18n:translate Dieses Attribute definiert Text, der durch das PHPTAL U:bersetzungssystem u:bersetzt werden soll.
Welcome here
Im obigen Beispiel wird PHPTAL nach einem U:bersetzungsschlu:ssel 'welcome_message' suchen und den Auszeichnungsinhalt durch die U:bersetzung in der gerade aktuellen Sprache ersetzen.
Welcome here
Hier ist die Verwendung ein wenig anders, da kein U:bersetzungsschlu:ssel angegeben worden ist. PHPTAL wird den Auszeichnungsinhalt 'Welcome here' als Schlu:ssel benutzen. Kennt das U:bersetzungssystem den Schlu:ssel 'Welcome here', ergibt das eine regelgerechte U:besetzung. Wird keine U:bersetzung gefunden, wird der Schlu:ssel als Ergebnis benutzt. Darum ist es sinnvoll lesbare Meldung statt Ku:rzel als Schlu:ssel zu verwenden. Beachten Sie bitte, das der Schlu:ssel, um eine dynamische Schlu:sselwahl zu ermo:glichen, auch in einer Variable enthalten sein kann.
...
i18n:attributes Dieses Attribut legt fest welche HTML Attribute u:bersetzt werden sollen. A:hnlich zu i18n:translate verlangt i18n:attributes eine durch Semikola getrennte Liste aus Attribute/Schlu:ssel Paaren. Picture i18n:name Dieses Attribut weist einer U:bersetzungsvariablen einen Wert zu. U:bersetzungen ko:nnen ${xxx} Zeichenketten enthalten in denen "xxx" den Namen einer Variablen bezeichnet, die dynamisch eingefu:gt werden soll. Diese Varibalen entha:lt die Auszeichnug und ihren Inhalt. Wird die Auszeichnug um den Inhalt herum nicht beno:tigt, benutzen Sie tal:replace anstatt tal:content. Falls der Wert aus verknu:pfung von Zeichenketten ist kann tal:omit-tag hilfreich sein. foo foo Ein Beispiel zur Benutzung von i18n:
Welcome , you have unread mails.
Der U:bersetzungsschlu:ssel lautet hier: "Welcome ${user}, you have ${mails} unread mails." PHPTAL wird ${user} durch ${user/name} und ${mails} durch ${user/nbrMails} in ihrer U:bersetzung ersetzen. Weiter Information zu I18N und PHPTAL finden sich im PHP Kapitel dieses Buches. XHTML in U:bersetzungen In der Grundeinstellung wird angenommen, das U:bersetzungen nur Text enthalten, daher maskiert PHPTAL sa:mtliche "<" Zeichen. Seit Version 1.1.14 ko:nnen Sie das structure Schlu:sselwort auch in i18n:translate verwenden, um die Maskierung zu unterbinden und den u:bersetzten Text unvera:ndert zu u:bernehmen.
Ergibt:
bold text
Vorbehalt: Dies funktioniert nur in den einfachsten Fa:llen - TAL Attribute innerhalb der U:bersetzungen werden ignoriert. Nicht wohlgeformtes XHTML in U:bersetzungen zersto:rt die Wohlgeformtheit der ganzen Ergebnisseite. PHPTAL Namensraum 1. phptal:debug 2. phptal:cache 1. Gesteuerte Auffrischung 2. Begrenzungen: 3. phptal:tales Diese Attribute sind nicht in den TAL Spezifikationen enthalten, aber sehr nu:tzlich fu:r die Arbeit mit PHPTAL. phptal:debug Dieses Attribut schaltet fu:r den Inhalt der Auszeichnung innerhalb derer es definiert ist das PHPTAL Debugging ein. Der Debugmodus speichert Informationen wie den Dateinamen und die Quellkodezeilennummer in der Vorlage, so dass Ausnahmemeldungen u:ber fehlerhafte Pfadzugriffen mehr Information u:ber das Wo enthalten. ...
...
phptal:cache Durch dieses Attribut wird ein komplettes Element, also Auszeichnung samt Attributen und Inhalt auf der Festplatte gepuffert und erst dann wieder neu interpretiert, wenn die Pufferzeit abgelaufen ist. Anmerkung Eine solche Pufferung lohnt sich nur fu:r Elemente, die sehr komplexe Ausdru:cke, Makros aus externen Dateien, oder PHP Ausdru:cke/Objekte mit Datenbankzugriffen enthalten. Ansonsten sind nichtgepufferte Vorlagen genau so schnell. Der Inhalt dieses Attributes ist eine Zeitspanne (wie lange soll das Element gepuffert werden), die als Zahl mit'd', 'h', 'm' oder 's' als Einheit geschrieben wird.
wird maximale alle 3 Stunden einmal ausgefu:hrt. Der Zeitspanne kann wahlweise ein "per" Parameter folgen, der festlegt, ob der Puffer geteilt wird. In der Grundeinstellung wird ein Elementpuffer von allen Seiten genutzt, die die entsprechende Vorlage nutzen. Sie ko:nnen ein "per url" hinzufu:gen, so dass jeder URL einen eigenen Puffer fu:r das betreffende Element erha:lt.
    wird fu:r jede Seite seperat einen Tag lang gepuffert. Um fu:r jeden einzelnen Wert eines Ausdrucks (der im Ergebnis eine Zeichenkette liefern muss) einen eigenen Puffer zu erhalten, ko:nnen Sie "per expression" verwenden. Dabei du:rfen sich die Ausdru:cke nicht auf Variablen beziehen, die via tal:define im der selben Auszeichnug definiert werden.
      ...
      wird fu:r jede object ID einzelnd 25 Minuten lang gepuffert. Gesteuerte Auffrischung Es ist eine gute Idee, anstatt einen Puffer zu lo:schen, in den per Parameter eine Versionsnummer oder einen Zeitstempel einzufu:gen. Dadurch wird die gepufferte Vorlage erneuert, sobald sich die Version oder der Zeitstempel a:ndert. Ein separates Pufferlo:schen ist dann nicht no:tig.
      ...
      Begrenzungen: o phptal:cache Blo:cke ko:nnen geschachtelt werden aber der a:ussere Block puffert die inneren unabha:ngig von ihrem Alter. o metal:fill-slot ko:nnen Sie in Auszeichnungen mit phptal:cache nicht verwenden. o phptal:tales Mit diesem Attribut la:sst sich das Verhalten von PHPTALES vera:ndern. In der Grundeinstellung werden PHPTAL Attribute eng an ZPT angelehnt interpretiert. In manchen Fa:llen bra:uchte man aber nur PHP und findet sich bei der sta:ndigen Verwendung des php: Operators wieder. Ein weiterer Punkt ist die Art und Weise in der PHPTAL Pfade auswerten muss. Zum Beispiel dauert die Auswertung von myobject/mymethod/property/10/othermethod/hashkey relativ lange (denken Sie daru:ber aber nicht zuviel nach - optimieren Sie erst, wenn Sie wirklich ein Problem mit dem Durchsatz haben!). Zur Laufzeit nimm sich PHPTAL myobject und findet heraus, dass es ein Objekt ist; stellt dann fest, dass mymethod eine Methode dieses Objektes (und keine Variable) ist und ruft sie auf; untersucht das Ergebnis um festzustellen, dass dies ein Objekt mit einer Eigenschaft ist; sieht, dass sein Wert ein Feld ist; greift sich das 10 Element dieses Feldes und bestimmt das das ein Objekt ist; entscheidet, dass othermethod eine Methode dieses Objektes (und keine Variable) ist und erha:lt das Ergebnis ihrer Ausfu:hrung; um dieses wiederum als Objekt zu erkennen und sich den Wert fu:r den Schlu:ssel hashkey zu holen. Natu:rlich ist das ein extremes Beispiel, und da das Ganze schnell genug ist, interessiert es zumeist nicht. Was geschieht aber, wenn ein solcher Pfad innerhalb eines grossen tal:repeat aufgerufen wird? Hmm... Hier kann phptal:tales hilfreich sein:
      Beachten Sie, dass obiges Beispiel dasselbe tut, wie:
      Der 'php:' Operator wird in einem eigenen Kapitel erla:utert. tal:block tal:block ist ein syntaktisches Zu:ckerchen fu:r Auszeichnungen, die viele TAL Attribute enthalten, die nicht ausgegeben werden. ist dasselbe wie: Ein weiteres Beispiel:
      ist dasselbe wie:
      PHPTALES 1. path: 2. Bedingte Anweisungen 3. string: 4. php: 5. not: 6. exists: 7. default 8. structure 9. Ausdrucksketten Zum Formulieren von Ausdru:cken innerhalb von tal, metal, PHPTAL Attributen wird PHPTALES verwendet. In den vorhergehenden Beispielen sind ihnen schon einige PHPTALES Beispielverwendungen (string:, php:, not:, ...) begegnet. Dieses Kapitel beschreibt nun die Anwendung PHPTALES in Vorlagen. Der Wert eines TAL Attributes darf mehr als einen Ausdruck enthalten (zB: tal:define). Dabei mu:ssen die einzelnen Ausdru:cke durch ';' getrennt werden. path: Das ist der Standardoperator der innerhalb eines TAL Ausdrucks verwendet wird, wenn kein anderer Operator angegeben wird. Folgende Zeilen liefern dasselbe Ergebnis: ${data/user/name} In der Vorlage oder in einem Ausdruck ko:nnen Sie auf eine bekannte Variable zugreifen, indem Sie ihren Pfad in der Form ${path/to/my/variable} angeben.

      ${document/title}

      Bedingte Anweisungen Da '<' und '>' aus Attributausdru:cken entfernt werden sollten, hat PHPTAL einige a:quivalente gute, alte, textuelle Vergleichsoperatoren. Diese Anweisungen treten hauptsa:chlich in tal:condition Attributen und in php: Ausdru:cken auf. o < : LT (kleiner als) o > : GT (gro:sser als) o <= : LE (kleiner oder gleich) o >= : GE (gro:sser oder gleich) string: Da Ausdru:cke mit Semikolon getrennt werden, und weil '$' Zeichen den Anfang eines Pfades markieren, mu:ssen Sie o ';;' verwenden, wenn Sie ein Semikolon in eine Zeichenkette einfu:gen wollen, o '$$' verwenden, wenn Sie ein '$' Zeichen in eine Zeichenkette einfu:gen wollen. string:foo $bar baz string:foo $$bar baz string:foo ; php:doFoo() string:foo ;; php:doFoo() php: Dieser Operator erwartet als Argument, bis auf zwei Ausnahmen, einen regula:ren PHP Ausdruck. '->' mu:ssen durch Punkte '.' ersetzt werden, und Variablennamen mu:ssen nicht mit einem vorangestellen Dollarzeichen '$' versehen werden. Ein vom Rest des Ausdrucks durch Leerzeichen getrennter Punkt '.' wird als Verkettungszeichen behandelt. php:htmlentities(foo) php:'string ${varReplaced}' php:'string ${some.path().to[0].var}' php:NOT foo OR (bar GT baz) php:a + b php:array('a', 'b', 'c') php:range(0, 90) php:foo . a.b.c(e) . htmlentities(SomeClass::staticMethod()) php:SomeClass::ConstOfClass php:SomeClass::$staticVar Verwenden Sie php: sparsam. In 80% ihrer Vorlagen werden Sie diesen Operator nicht beno:tigen, aber manchmal werden Sie eine spezielle PHP Methode aufrufen mu:ssen, z.B. um sich zu vergewissern, dass ein Benutzer angemeldet ist, oder um spezielle, komplexe Daten, in Abha:ngigkeit von einigen Bedingungen, innerhalb der Vorlage dynamisch zu laden. not: Dieser Operator bewirkt eine boolsche Negation. Er wird in tal:condition Ausdru:cken verwendet. not logged exists: Dieser boolsche Operator gibt wahr (true) zuru:ck, wenn der getestete Pfad existiert und falsch (false) sonst. Er funktioniert analog zur php isset() Funktion. Normalerweise liefert die Verwendung eines nicht existierenden Pfades eine Fehlermeldung wie "Cannot find variable 'foo' in current scope". Darum sollten unsichere Pfade vor der Verwendung immer gepru:ft werden: user preferences here if defined default Dies ist kein Operator, sondern ein Schlu:sselwort, dass es Vorlagenentwicklern erlaubt, im Falle eines Fehlers, oder wenn etwas nicht definiert ist, den Inhalt einer Auszeichnung als Ersatzwert zu verwenden. default my var value no some/var and no other/path found here Unknown page Das obigen Beispiele fu:hrt das '|' Zeichen ein, dass fu:r Definitonen oder Ausgaben die Festlegung von Alternativen ermo:glicht. structure Dies ist kein Operator, sondern ein Schlu:sselwort. Bei der Ausgabe von Variablen innerhalb von PHPTAL Vorlagen kodiert PHPTAL alle HTML/XML eigenen Zeichen um sicherzustellen, dass das Ausgabedokument gu:ltig ist. Es kommt vor, dass Sie HTML/XML Variablen verwenden, die unvera:ndert ausgegeben werden sollen:

      Im obigen Beispiel wird angenommen, dass $document->title und $document->content Variblen sind, die vorformatiertes HTML enthalten, das, so wie es ist, ausgegeben werden soll. Ausdrucksketten Ein Ausdruckskette ist eine durch das '|' Zeichen getrennte Liste von Ausdru:cken. PHPTAL wertet die Ausdru:cke in einer solchen Kette von vorne nach hinten aus, bis der erste Ausdruck ein nicht Null Ergebnis, das keine Fehlermeldung ist, zuru:ckliefert. Dannach bricht die Auswertung ab. Da ein string: Ausdruck immer wahr ist, wird die Auswertung durch einen string: Ausdruck immer beendet. Innerhalb von Ausdrucksketten ko:nnen Sie, wie jeden anderen Ausdruck, auch Ausdru:cke mit dem php: Operator verwenden:

      You can perfectly well choose to specify the template source after setting context variables. set('title', 'my title'); $tpl->set('values', array(1,2,3,4)); $tpl->set('user', new User('Joe')); $tpl->setTemplate('mytemplate.xhtml'); ?> You can also decide to use a generated string as the template source instead of using an existing template file: my title

      my title

      EOS; require_once 'PHPTAL.php'; $tpl = new PHPTAL(); $tpl->setSource($src); $tpl->title = 'this is my title'; try { echo $tpl->execute(); } catch (Exception $e){ echo $e; } ?> In the above example, because PHPTAL requires a template source idenfifier (usually the template file realpath), PHPTAL will use the md5 of the $src parameter as a unique identifier. You may decide to force the identifier using a second setSource() argument: my title

      my title

      EOS; require_once 'PHPTAL.php'; $tpl = new PHPTAL(); // because the source is contained in this file and won't be modified unless // this file is modified, it is 'faster' to specify __FILE__ as the unique // source identifier, thus no md5 of $src will be done on each call. $tpl->setSource($src, __FILE__); $tpl->title = 'this is my title'; try { echo $tpl->execute(); } catch (Exception $e){ echo $e; } ?> interface PHPTAL_Filter This interface allows you to automatically filter templates sources (pre-filters) or PHPTAL result (post-filters). Pre filters are invoked before the template parsing and won't be invoked until the source template file is modified. Post filters are invoked after each template execution. setPreFilter(new MyPreFilter()); $tpl->setPostFilter(new MyPostFilter()); echo $tpl->execute(); ?> You can set only one pre-Filter and one post-Filter using set*Filter. If you have more than one filter to chain, you can wrap them into a single class, implementing the PHPTAL_Filter interface, which would invoke the filter's chain. _filters[] = $filter; } public function filter($source){ foreach($this->_filters as $filter){ $source = $filter->filter($source); } return $source; } } $myfilter = new FilterChain(); $myfilter->add(new CommentFilter()); // imaginary filter $myfilter->add(new TidyFilter()); // imaginary filter $tpl = new PHPTAL('mytemplate.xhtml'); $tpl->setPostFilter($myFilter); echo $tpl->execute(); ?> interface PHPTAL_Trigger The phptal:id attribute was added into the PHPTAL for the PHP5 version to replace the old PHPTAL_Cache interface and to abstract it a little more. When a phptal:id is reached, PHPTAL will look in its triggers list for a matching id and will invoke the trigger start() and end() methods before entering the element, and just after it. If the PHPTAL_Trigger::start() methods returns PHPTAL_Trigger::SKIPTAG, PHPTAL will ignore the element and its content (start() may echo something to replace it). If your trigger wants the element and its content to be executed, you'll have to return PHPTAL_Trigger::PROCEED. The PHPTAL_Trigger::end() will be called after the element (whether it has been executed or not). This allows you to build cache systems using ob_start() in start() and ob_get_contents(), ob_end_clean() in end().
      foo bar baz foo bar baz
      For some reason we decide the div block requires to be cached. We introduce a phptal:id into the template: ...
      ... foo bar baz foo bar baz ...
      ... Then we write our trigger which will cache the div content: _cachePath = 'cache.' . $tpl->getContext()->id; // if already cached, read the cache and tell PHPTAL to // ignore the tag content if (file_exists($this->_cachePath)){ $this->_usedCache = true; readfile($this->_cachePath); return self::SKIPTAG; } // no cache found, we start an output buffer and tell // PHPTAL to proceed (ie: execute the tag content) $this->_usedCache = false; ob_start(); return self::PROCEED; } // Invoked after tag execution public function end($phptalid, $tpl) { // end of tag, if cached file used, do nothing if ($this->_usedCache){ return; } // otherwise, get the content of the output buffer // and write it into the cache file for later usage $content = ob_get_contents(); ob_end_clean(); echo $content; $f = fopen($this->_cachePath, 'w'); fwrite($f, $content); fclose($f); } private $_cachePath; private $_usedCache; } ?> The key here is to return from start() with either SKIPTAG or PROCEED. When SKIPTAG is returned, PHPTAL will just ignore the tag and call end(). This usually means that the trigger takes the hand in deciding what to show there. When PROCEED is returned, PHPTAL will execute the tag and its content as usual, then call end(). This allows our cache class to play with output buffers to execute the tag once and to store the result in a file which will be used in later calls. To install our trigger we use: addTrigger('somePossiblyUniqueKeyword', $trigger); $tpl->id = 1; echo $tpl->execute(); ?> You can add as many triggers as you like to your templates. A generic cache trigger may also handle more than one phptal:id... etc... interface PHPTAL_TranslationService 1. method setLanguage(...) 2. method useDomain($domain) 3. method setVar($key,$value) 4. method translate($key) PHPTAL comes with a default gettext translation service, as shown in another section. For some reason you may prefer to implement your own service of translation. The PHPTAL_TranslationService interface is here to serve your needs. The usage of your service will be the same as the PHPTAL_GetTextTranslator. $tpl->setTranslator($yourOwnTranslatorInstance); Ihre Implementierung muss die folgenden Methoden definieren: method setLanguage(...) Diese Methode kann durch die Vorlage aufgerufen werden um die aktuelle Ausgabesprache zu a:ndern. Die Argumente sind eine Liste von mo:glichen Sprachen (verwenden Sie func_get_args() um die Argumentenliste zu erhalten). Ihr Dienst sollte dann die erste bekannte Sprache wa:hlen. _currentLang = $lang; return; } } ... private $_currentLang; } ?> method useDomain($domain) If you decided to store your translations into separate files, one for each application, for example, this method allows you to select the translation domain from your templates (i18n:domain). _domains)){ $file = "domains/$this->_currentLang/$domain.php"; $this->_domains[$domain] = include($file); } $this->_currentDomain = $this->_domains[$domain]; } ... private $_currentDomain; private $_domains = array(); } ?> Das obige Beispiel ist eine mo:glich U:bersetzungslo:sung, bei der die Schlu:ssel in PHP Dateien gespeichert werden, die ein assoziatives key => translation Feld zuru:ckgeben. method setVar($key,$value) This method matches i18n:name calls. It builds an interpolation context for later translate calls. _context[$key] = $value; } ... private $_context = array(); } ?> method translate($key) The last and most important method to implement, it asks your service to translate the specified key for the currently selected language. _currentDomain[$key]; // interpolate ${myvar} using context associative array while (preg_match('/\${(.*?)\}/sm', $value, $m)){ list($src,$var) = $m; if (!array_key_exists($var, $this->_context)){ $err = sprintf('Interpolation error, var "%s" not set', $var); throw new Exception($err); } $value = str_replace($src, $this->_context[$var], $value); } return $value; } ... } ?> Die Arbeit mit gettext 1. Erzeugung der U:bersetzungsverzeichnisstruktur (Hmpf) 2. Portable Object files 3. Translation Domain 4. PHP usage in PHPTAL 5. Variable interpolation gettext ist der GNU Standard fu:r das Internationalisierungs und U:bersetzungssystem. Es kann im Zusammenspiel mit PHP benutzt werden und wird von PHPTAL unterstu:zt. Die Benuzung von gettext ist einfach, aber Sie sollten einige tests durchfu:hren, um sicherzustellen, dass auf ihrem rechner alles richtig zusammenspielt. PHP muss mit dem --with-gettext Schalter kompiliert werden. Na:heres dazu findet sich in der PHP Dokumentation. Mit dem folgenden Stu:ckchen Code ko:nnen Sie ihre PHP Installation daraufhin pru:fen: // // test if gettext extension is installed with php // if (!function_exists("gettext")) { echo "gettext is not installed\n"; } else { echo "gettext is supported\n"; } Erzeugung der U:bersetzungsverzeichnisstruktur (Hmpf) Die PHP gettext Erweiterung verlangt nach einer bestimmten Verzeichnissstruktur, die die U:bersetungsdateien entha:lt. /path/to/your/translation_root/en_US/LC_MESSAGES/ /path/to/your/translation_root/en_GB/LC_MESSAGES/ /path/to/your/translation_root/fr_FR/LC_MESSAGES/ /path/to/your/translation_root/es_ES/LC_MESSAGES/ ... and so on ... Die Sprachkode besteht aus zwei Zeichen, die die eigentliche Sprache (fr, de, it, ...) und zwei Zeichen, die das Land (CH, DE, IT, ...) festlegen. Das Verzeichnismuster sieht so aus: //LC_MESSAGES/ Portable Object files PO Dateien sind Klartextdateien die die U:bersetzungen enthalten. Sie ko:nnen sie problemlos ha:ndisch editieren. minimalistisches po Beispiel (en_US/LC_MESSAGES/mydomain.po): msgid "" msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Simple test" msgstr "A small sentence in english" Einmal bearbeitet, muss jede PO Datei indiziert werden: msgfmt mydomain.po -o mydomain.mo Dieser Aufruf funktioniert nicht, wenn Sie die gettext Werzeuge auf ihrem System nicht installiert haben. Hierdurch wird eine MO Datei (machine object) erzeugt, in der ihre U:bersetzung fu:r einen schnellen Zugriff indiziert vorliegen. Nun mu:ssen Sie diese Datei in andere Sprachen u:bersetzen. minimalistisches po Beispiel (fr_FR/LC_MESSAGES/mydomain.po): msgid "" msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Simple test" msgstr "Une petite phrase en franc,ais" Auch die U:bersetzungsdatei muss indiziert werden: msgfmt mydomain.po -o mydomain.mo Translation Domain The domain is matched against your translation file names. In above examples we used 'mydomain' as domain name. You can have more than one domain for the same application, it can enhance gettext's performance to split your application translations in more than one file. PHP usage in PHPTAL setLanguage('en_GB.utf8', 'en_GB'); // register gettext domain to use $tr->addDomain('mydomain', '/path/to/your/translation_root'); // specify current domain $tr->useDomain('mydomain'); $tpl = new PHPTAL('mytemplate.xhtml'); // tell PHPTAL to use our translator $tpl->setTranslator($tr); } catch (Exception $e){ echo $e; } Variable interpolation The I18N Namensraum allows some variable interpolation in your translations. # english msgid "welcome" msgstr "Welcome ${name} you have ${n} mails!" # french msgid "welcome" msgstr "Bienvenue ${name} vous avez recu ${n} messages!" A template can use this interpolation as follows: Welcome you currently have unread messages! Because i18n:translate contains a value 'welcome', the template data will be ignored and the message given by gettext will be used instead. Massgeschneiderte Operatoren entwickeln PHPTAL entha:lt einige grundlegende Operatoren: "not:", "exists:", "string:", "php:", "path:". Diese Operatoren sind in den ZPT Spezifikationen definiert. PHPTALES kann mit eigenen Operatoren zur Bearbeitung von Zeichenketten, Kalenderdaten, Wa:hrungen, oder was auch immer erweitert werden. Ziel der Anwendung jedweden Operators ist es, ein Stu:ckchen PHP Code zuru:ckzugeben, der in den aus der Vorlage generierte PHP Code integriert wird. Operatoren werden wa:hrend der Vorlagenzerlegung angewendet. Wenn sie das Verhalten eines Operators vera:ndern, mu:ssen sie alle vorher erzeugten PHP Dateien lo:schen und die Vorlagen neu zerlegen lassen. Beachten Sie, dass Operatoren Code und keine Daten ausgeben! Jede PHP Funktion die mit "phptal_tales_" beginnt, ist als Operator verwendbar. Operatoren erwarten zwei Argumente:: o $src: the source string after the "modifier:" keyword o $nothrow: a boolean which determines whether exceptions may be thrown or not by phptal_path() resolution. This boolean must be propagated whenever you call another phptal_tales_* modifier from within your own modifier. For example, in the following TAL template, The src argument will be "my/path/value", and the $nothrow boolean will be false, because tal:replace requires the path to be fully resolvable. Ein Ausdruck wie: nutzt zwei Operatoren: o some-modifier: with "my/path/value" as $src argument and $nothrow set to true because an alternative exists o path: with "other/path" as $src, and $nothrow set to false because in case the alternative is not found, tal:replace will be in trouble. Zur Erinnerung: path: wird implizit verwendet, sollte kein anderer Operator angegeben sein. Operatoren ko:nnen andere Operatoren verwenden um einfacheren php Code zu erhalten, siehe das folgende Beispiel. // // This modifier will return a money formated string (XXX.XX) // // usage: // // money: path/to/my/amount // // this modifier uses phptal_tales() function to generate the // PHP code that will return the value of the modifier argument. // // in the example: // // money: path/to/my/amount // // the produced code will be something looking like: // // sprintf("%01.2f", phptal_path($ctx->path, "to/my/amount")) // // This code will be included right into the template where needed. // // @param string $src // The expression string // @param string $nothrow // A boolean indicating if exceptions may be throw by phptal_path if // the path does not exists. // @return string // PHP code to include in the template // function phptal_tales_money( $src, $nothrow ) { // remove spaces we do not require here $src = trim($src); return 'sprintf("%01.2f", '.phptal_tales($src, $nothrow).')'; } Hinweis fu:r Systembetreuer ---------------------------------------------------------------------- PHPTAL arbeitet, indem es PHP Dateien aus der Vorlagenlogik generiert; das bedeutet, dass es ein Verzeichniss beno:tigt, in dem die erzeugten Dateien gespeichert und durch den PHP Interpreter zerlegt werden ko:nnen. In der Grundeinstellung verwendet PHPTAL, falls vorhanden, die PHP sys_get_temp_dir() Funktion um das tempora:re Verzeichniss zu bestimmen in dem die generierten PHP Dateien gespeichert werden. Sonst wird auf unixartigen Systemen /tmp und auf Microsoft Systemen c:\windows\temp verwendet. Sie ko:nnen die Grundeinstellung durch den Aufruf von setPhpCodeDestination() mit einem passenden Pfad nach ihren Wu:nschen a:ndern. Sei es das u:bliche tempora:re Verzeichniss, sei es ein eigenes: seine Zugriffsrechte mu:ssen so gesetzt sein, dass der PHP ausfu:hrenden Prozess (d.h. der Apache Betreiber wenn das mod_php Modul verwendet wird, sonst der cgi/fastcgi Betreiber) Dateien anlegen und vera:ndern kann. PHPTAL erzeugt zu jeder Vorlagendatei und, falls phptal:cache verwendet wird, auch fu:r jedes Element eine (php) Datei. Fu:r Makros werden keine separaten Dateien angelegt. (Sie werden einfach als PHP Funktionen in die erzeugte Datei eingefu:gt.) Diese Dateien werden ab und an automatisch gelo:scht, genauer: jedes mal, wenn eine Vorlage bearbeitet wird, wird die alte Datei mit einer gewissen, durch setCachePurgeFrequency() bestimmten Wahrscheinlichkeit, gelo:scht, falls ihre durch setCacheLifetime() festgelegte Lebensdauer abgelaufen ist. Natu:rlich kann man alte bzw. unbenutzte Dateien auch via cron Job und shell lo:schen (hier: UNIXartige Shell): find /tmp/ -name tpl_\* \( -atime +1 -o -mtime +14 \) -exec rm -v {} \; Nu:tzliche Verweise ---------------------------------------------------------------------- o ZPT die Zope Page Template Startseite, o TAL die Template Attribute Language Seite, o METAL die Makroerweiterung zu TAL, o TALES die Definition der TAL Ausdru:cke. Danksagungen ---------------------------------------------------------------------- Vielen Dank an: o Das ZPT Team, das diese nu:tzlichen Spezifikationen entwickelt hat, o die PHPTAL Gemeinschaft fu:r ihre Unterstu:tzung, Hilfe und ihre Hinweise, o Jean-Michel Hiver, der mich zum Draufschauen'zwang', o Olivier Parisy, den ersten enthusiastischen PHPTAL Benutzer und bug Finder,