Adventure,PHP,Framework,PageController,FrontController,Pattern,Objektorientierung,OO,Software,Design,Wiederverwendbarkeit,UML,Tutorial,Benchmark,ausgezeichnete Performance

Suche:    
Downloads  |  SVN!  |  Roadmap  |  Forum!  |  Bugtracking  |  Gästebuch  |  Backlinks!  |  Referenzen!  |  Sitemap  |  Impressum  
 
Deutsch | English Adventure PHP Framework  Bookmark @ Technorati Bookmark @ del.icio.us Bookmark @ Mr. Wong Bookmark @ Simpy Bookmark @ Google Bookmark @ Digg.com Adventure PHP Framework Seite 045-TagLibs-erstellen drucken!
TagLibs erstellen

Artikel bewerten:
Dieser Artikel wurde von 6 Leser(n) mit
Adventure PHP Framework Artikel bewertenAdventure PHP Framework Artikel bewerten (1.1)
von 5 Punkten bewertet. Bewerten auch Sie diesen Artikel!

1. Einführung

Der hier diskutierte Page-Controller baut beim Parsen der Templates einen internen Objektbaum aus den Implementierungen der einzelnen TagLib-Klassen auf. Als Basis für alle vorhandenen und weiteren Baum-Objekte dient die Klasse Document. Dieses erbt bereits vom zentralen Basis-Objekt coreObject und besitzt in ihrer Spezialisierung die zentrale Parser-Methode __extractTagLibTags(). Jeder in einem Template notierte XML-TgLib-Tag bildet im DOM-Baum ein weiteres Kind des aktuellen Dokuments. Der XML-Tag in einer Template-Datei definiert dabei die Parameter des Tags, die TagLib-Klasse die Funktion desselben zum Zeitpunkt des Parsen und bei der Transformation.


2. Aufbau einer TagLib

Jeder XML-Tag, der unter Standard-TagLibs dokumentiert ist, wird - wie oben beschrieben - durch eine TagLib-Klasse repräsentiert. Die TagLib-Klasse definiert dabei über die Interface-Methoden das Verhalten des Tags zur Laufzeit der Anwendung.

Eine TagLib-Klasse besitzt immer den Namensbestandteil "_taglib_" zwischen Präfix und Klassenbezeichnung. Möchte der Entwickler in einer Template-Datei das Tag
  <shop:basket />
einbauen, so ist die TagLib-Klasse
  shop_taglib_basket
zu benennen. Dabei wird der grün markierte Teil als Präfix und der blau markierte Teil Klasse bezeichnet. Die Vergabe von Präfix und Klasse obligt dem Entwickler. Es wird jedoch empfohlen, die Tags nach Abhängigkeit und Schachtelung zu bezeichnen. Besitzt der <shop:basket />-Tag beispielsweise weitere Sub-Tags, so sollte das Präfix dieser mit basket betitelt werden. Hier ein Beispiel für die sinnvolle Benennung:
  <shop:basket>
    <basket:title />
    <basket:products>
      <products:listing />
      <products:sum />
    </basket:products>
  </shop:basket>

Da an dieser Stelle gewünscht ist, dass bei Parsen des <shop:basket />-Tags weitere Sub-Tags berücksichtigt werden, müssen diese der shop_taglib_basket-Klasse im Konstruktur durch
   class shop_taglib_basket extends Document
   
{

      function 
shop_taglib_basket(){
         
$this->__TagLibs[] = new TagLib('namespace::to::taglib','basket','title');
         
$this->__TagLibs[] = new TagLib('namespace::to::taglib','basket','products');
       
// end function
      
}

      [..]

    
// end class
   
bekannt gemacht werden. Selbiges gilt für das Tag <basket:products /> in der TagLib basket_taglib_products. Auch hier müssen die TagLibs <products:listing /> und <products:sum /> im Konstruktor von basket_taglib_products bekannt gemacht werden.


2.1. Klassen-Variablen

Beim Parsen des XML-/HTML-Codes einer HTML-Datei werden die eingesetzten und dem Parser bekannten Tags in Objekte gemappt. Der Inhalt eines Tags, z.B.
 <php:hightlight>
   $var = 'value';
 </php:hightlight>
wird in die Variable $this->__Content geschrieben, die Attribute des Tags in die Variable $this->__Attributes, wobei letzteres vom Typ Array ist. Damit kann innerhalb einer TagLib immer auf den Inhalt und die Attribute desselben zugegriffen werden. Tags können damit ganz einfach im XML-/HTML-Code für die Verwendung parametrisiert/konfiguriert werden. Weiterer Vorteil ist, dass einem so eingesetzten Tag beliebig viele HTML-Attribute wie "style" oder "class" zugewiesen werden können. Dies erleichtert vor allem bei UI-Elementen wie Text-Felder oder Buttons die Formatierung unabhängig vom PHP-Code.
Die private Variable $this->__ParentObject hält eine Referenz auf das Vater-Objekt. Somit kann mit den Methoden get(), set(), getAttribute() und setAttribute() auf die Eigenschaften der Eltern-Klasse zugegriffen werden. Die Funktionen getByReference() und setByReference() ermöglichen zudem Referenzen auf diverse Objekte im Baum zu holen, oder den adressierten Objekten Referenzen auf diverse Objekte mit zu geben. Die Dokumentation der Methoden kann unter der API-Dokumentation des Core-Namespaces für das Objekt Document bzw. coreObject nachgelesen werden.


2.2. Klassen-Methoden

Um einer Tag-Library Funktionen "mitgeben" zu können gibt es mehrere Interface-Methoden, die zu unterschiedlichen Zeiten ausgeführt werden und unterschiedliche Bedeutung haben. Grundsätzlich ist der Entwickler jedoch frei in der Gestaltung der Klasse selbst und kann diese durch beliebige Methoden erweitern. Bindend bzw. vorgegeben sind jedoch folgende Bereiche:
  • Klassen-Deklaration:
    Die Klasse muss stets von Document erben, da diese das Interface für die konkrete Implementierung vorgibt und die zentrale Parser-Methode zur Verfügung stellt. Der Dateiname richtet sich nach der Wahl des Tag-Namens. Wird der Tag "php:highlight" genannt, so bildet der erste Teil (Präfix) den ersten Teil des Namens vor dem Mittel-Teil "_taglib_" und der zweite Teil (Class) das Suffix. Es ergibt sich somit ein Klassen-Name von php_taglib_highlight. Wird eine TagLib mit dem "core:addtaglib"-Tag eingebunden sucht der Parser nach einer derart benannten Datei. Wichtig ist ausserdem, dass die Dateinamen mit dem der Klasse übereinstimmen muss.

  • Konstruktor:
    Im Konstruktor einer TagLib können einfache Initialisierungen von Member-Variablen oder ähnliche Aufgaben platziert sein. Beim Erzeugen des Objekts wird dem Konstruktor kein Parameter übergeben. Es muss nicht zwingend ein Konstruktor implementiert werden.
    Ein weiterer Anwendungsfall ist das Hinzufügen weiterer TagLibs, die als Kinder eines Tags fungieren (siehe oben). Ein Beispiel hierfür ist zudem die Klasse html_taglib_template (siehe API-Dokumentation).

  • onParseTime()-Implementierung:
    Die Methode onParseTime() wird auf jede TagLib dann ausgeführt, wenn die Eigenschaften

    • $this->__Context
    • $this->__Attributes
    • $this->__Content
    • $this->__Language

    vom PageController gesetzt wurden. Damit hat die Tag-Library bereits zu diesem Zeitpunkt Zugriff auf die Attribute und Inhalte und kann Operationen implementieren. Es ist zu diesem Zeitpunkt jedoch noch nicht sichergestellt, dass alle Kinder des aktuellen Dokuments erzeugt und eingehängt wurde. Um Zugriff auf diese zu erhalten sollte die Funktion onAfterAppend() genutzt werden.

    Tipp:
    Die Methode eignet sich jedoch um weitere Sub-Tags im Inhalt des aktuellen Objekts zu parsen oder etwaig angegebene DocumentController zu extrahieren. Hier stehen die privaten Methoden __extractTagLibTags() und __extractDocumentController() (siehe API-Dokumentation) zur Verfügung.

  • onAfterAppend()-Implementierung:
    Sind alle Kinder des aktuellen Knotens in den Baum eingehängt, wird auf diese jeweils die onAfterAppend()-Methode ausgeführt. Von hier aus kann nun auf alle Objekte des Baumes zugegriffen werden. In der Variablen $this->__ParentObject ist eine Referenz auf das Vater-Objekt und in $this->__Children sind die Kinder eines Objekts gespeichert. Mit den oben genannten Methoden kann auf die Attribute und Eigenschaften zugegriffen werden.

  • transform()-Implementierung
    Die bisher genannten Methoden dienten dem Abbilden des XML-/HTML-Codes in einen Objektbaum. Die Funktion transform() hingegen ist für die Generierung der HTML-Ausgabe zuständig. Hier wird der HTML-Code generiert, der nach der vollständigen Transformation des Baumes zu Anzeige gebracht wird. In der Regel kann die Implementierung der Methode von der Klasse Document übernommen werden, für spezielle Anwendungen muss diese jedoch überladen werden. Um die Attribute eines Objekts in HTML-Code ausgeben zu können gibt es eine weitere private Helper-Methode: __getAttributesAsString().

3. Anwendungsbeispiele

3.1. Taglib php_taglib_hightlight

Folgender Code zeigt ein Beispiel für eine einfache TagLib, die im Text zwischen
  <php:highlight>
    [..]
  </php:highlight>
enthaltenen PHP-Code farbig darstellt. Die Logik wird dabei von der Klasse php_taglib_hightlight abgebildet. Diese implementiert dazu die Methode transform(), in der der in der Variable $this->__Content enthaltene Text mit Hilfe der PHP-Funktion highlight_string() als PHP-Quelltext formatiert wird:

<?php
   
/**
   *  @package sites::demosite::pres::taglib
   *  @module php_taglib_highlight
   *
   *  Implementiert die Tag-Library für das PHP-Code-Highlightning.<br />
   *
   *  @author Christian Schäfer
   *  @version
   *  Version 0.1, 08.04.2007<br />
   */
   
class php_taglib_highlight extends Document
   
{

      function 
php_taglib_highlight(){
      }


      
/**
      *  @module transform()
      *  @public
      *
      *  Implementiert die Interface-Methode "transform()", mit dem ein Objekt in HTML transformiert wird.<br />
      *
      *  @author Christian Schäfer
      *  @version
      *  Version 0.1, 08.04.2007<br />
      *  Version 0.2, 05.05.2007 (PHP-Tags werden nun nicht mehr mit ausgegeben)<br />
      *  Version 0.3, 01.07.2007 (Probleme mit verschobenen Quelltexten behoben. Klasse "div.phpcode" wird zur Formatierung verwendet)<br />
      *  Version 0.4, 21.08.2007 (Rudimentärer PHP-5-Support, da highlight_string() dort anderes tickt)<br />
      *  Version 0.5, 16.09.2007 (PHP-5-Support verbessert)<br />
      *  Version 0.6, 02.01.2008 (Höhe der Code-Box auf 400px begrenzt)<br />
      */
      
function transform(){

         
// Anzahl der Zeilen speichern
         
$LineCount substr_count($this->__Content,"\n") - 1;

         
// Quelltext highlighten
         // - Zeilenumbrüche am Anfang entfernen
         // - Leerzeichen und Zeilenumbrüche am Ende entfernen
         // - Leerzeichen und Zeilenumbrüche um den kompletten Text entfernen
         
$HighlightedContent highlight_string(trim('<?php '.ltrim(rtrim($this->__Content),"\x0A..\x0D").' ?>'),true);

         
// PHP-Anfangstag ersetzen
         
$HighlightedContent str_replace('<font color="#007700">&lt;?</font>','',$HighlightedContent);
         
$HighlightedContent str_replace('<font color="#0000BB">&lt;?php&nbsp;','<font color="#0000BB">',$HighlightedContent);
         
$HighlightedContent str_replace('<font color="#0000BB">php','<font color="#0000BB">',$HighlightedContent);
         
$HighlightedContent str_replace('<font color="#0000BB">&nbsp;</font>','',$HighlightedContent);

         
// Erweiterung für PHP 5-Verhalten
         
$HighlightedContent str_replace('<span style="color: #0000BB">&lt;?php&nbsp;','<span style="color: #0000BB">',$HighlightedContent);
         
$HighlightedContent str_replace('<span style="color: #0000BB">&lt;?php','<span style="color: #0000BB">',$HighlightedContent);
         
$HighlightedContent str_replace('<span style="color: #0000BB">?&gt;</span>','',$HighlightedContent);

         
// PHP-Endtag ersetzen
         
$HighlightedContent str_replace('<font color="#0000BB">?&gt;</font>','',$HighlightedContent);

         
// Code im DIV zurückgeben (Höhe begrenzen, falls notwenig)
         
if($LineCount 27){
            return 
'<div class="phpcode" style="height: 400px; overflow: auto;">'.$HighlightedContent.'</div>';
          
// end if
         
}
         else{
            return 
'<div class="phpcode">'.$HighlightedContent.'</div>';
          
// end else
         
}

       
// end function
      
}

    
// end class
   
}
?>


3.2. Taglib html_taglib_entityencode

Die TagLib html:entityencode dient dazu Text in HTML-Entities zu konvertieren. Ein wichtiges Anwendungsgebiet ist die Codierung einer E-Mail-Adresse um diese von Crawlern zu schützen. Um diese Funktionalität bereitzustellen wird eine neue TagLib-Klasse definiert, die die Methode encodeCharactersToHTML der Klasse stringAssistant nutzt, um den Inhalt des Tagszu konvertieren. Nach dem Einbinden der TagLib kann diese wie folgt verwendet werden:

  <html:entityencode>nobody@example.com</html:entityencode>
Im Quelltext der ausgelieferten Seite findet sich dann der Text
&#110;&#111;&#98;&#111;&#100;&#121;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;
wieder. Da die Codierungs-Funktionalität nicht in der TagLib selbst implementiert ist, kann diese auch in anderen Bereichen wie einem Gästebuch durch Einbindung der Klasse stringAssistant verwendet werden. Die nachfolgend angezeigte Quelltext-Box zeigt die TagLib nochmal im Überblick:

<?php
   import
('tools::string','stringAssistant');


   
/**
   *  @package sites::demosite::pres::taglib
   *  @module html_taglib_entityencode
   *
   *  Implementiert die Tag-Library für das konvertieren von Text in HTML-encoded Characters.<br />
   *
   *  @author Christian Schäfer
   *  @version
   *  Version 0.1, 24.06.2007<br />
   */
   
class html_taglib_entityencode extends Document
   
{

      function 
html_taglib_entityencode(){
      }


      
/**
      *  @module transform()
      *  @public
      *
      *  Implementiert die Interface-Methode "transform()", mit dem ein Objekt in HTML<br />
      *  transformiert wird.<br />
      *
      *  @author Christian Schäfer
      *  @version
      *  Version 0.1, 24.06.2007<br />
      */
      
function transform(){
         return 
stringAssistant::encodeCharactersToHTML($this->__Content);
       
// end function
      
}

    
// end class
   
}
?>


3.3. Taglib doc_taglib_createobject

Als weiteres Anwendungs-Beispiel soll die Tag-Library erläutert werden, die für die Einbindung des Inhalts der Dokumentations-Seite verantwortlich ist. Die Tag-Library <doc:createobject /> liest Inhalte aus HTML-Dateien in einem speziellen Ordner aus, parst den Inhalt und generiert dadurch eine weitere Verzweigung im Objektbaum. Der folgende Kasten zeigt den Quell-Code der TagLib. Um diese nutzen zu können muss diese zuerst mit
  <core:addtaglib namespace="tools::html::taglib" prefix="doc" class="createobject" />
eingebunden werden. Anschließend (bereits unmittelbar nach dem Einbinden) kann folgendes in der HTML-Datei notiert werden:
  <doc:createobject requestparam="Seite" defaultvalue="Startseite" />
Betrachtet man den Quellcode der TagLib-Klasse näher wird dort folgende Logik gekapselt:

<?php
   import
('tools::variablen','variablenHandler');


   
/**
   *  @package tools::html::taglib::doc
   *  @class doc_taglib_createobject
   *
   *  Implementiert die TagLib für den Tag "doc:createobject".<br />
   *
   *  @author Christian Schäfer
   *  @version
   *  Version 0.1, 04.01.2006<br />
   *  Version 0.2, 29.09.2007 (TagLib in doc_taglib_createobject umbenannt)<br />
   */
   
class doc_taglib_createobject extends Document
   
{

      
/**
      *  @public
      *
      *  Konstruktor der Klasse. Ruft den Konstruktor der Eltern-Klasse auf.<br />
      *
      *  @author Christian Schäfer
      *  @version
      *  Version 0.1, 04.01.2006<br />
      *  Version 0.2, 29.09.2007 (Methode in doc_taglib_createobject umbenannt)<br />
      */
      
function doc_taglib_createobject(){
         
parent::Document();
       
// end function
      
}


      
/**
      *  @public
      *
      *  Implementiert die abstrakte Methode onParseTime().<br />
      *
      *  @author Christian Schäfer
      *  @version
      *  Version 0.1, 04.01.2006<br />
      */
      
function onParseTime(){

         
// Attribute auslesen
         
$RequestParameter $this->__Attributes['requestparam'];
         
$DefaultValue $this->__Attributes['defaultvalue'];

         
// Parameter über variablenHandler initialisieren
         
$_LOCALS variablenHandler::registerLocal(array($RequestParameter => $DefaultValue));

         
// Aktuellen Parameter auslesen
         
$CurrentRequestParameter $_LOCALS[$RequestParameter];

         
// Content des Objekts setzen
         
$this->__Content $this->__getContent($CurrentRequestParameter);

         
// Tags extrahieren
         
$this->__extractTagLibTags();

         
// DocumentController extrahieren
         
$this->__extractDocumentController();

       
// end function
      
}


      
/**
      *  @private
      *
      *  Liest den Inhalt einer Seite aus der zugehörigen Datei aus. Im Fehler-<br />
      *  Fall wird eine 404-Seite angezeigt.<br />
      *
      *  @author Christian Schäfer
      *  @version
      *  Version 0.1, 30.05.2006<br />
      *  Version 0.2, 31.05.2006 (Content aus Namespace /apps/sites in Webseiten-Repository (frontend/content) verschoben)<br />
      *  Version 0.3, 29.09.2007 (Sprachabhängige Seiten eingeführt)<br />
      */
      
function __getContent($Seite){

         
$Datei './frontend/content/c_'.$this->__Language.'_'.strtolower($Seite).'.html';

         if(!
file_exists($Datei)){
            
$Datei './frontend/content/c_'.$this->__Language.'_404.html';
          
// end else
         
}

         return 
file_get_contents($Datei);

       
// end function
      
}

    
// end class
   
}
?>

  • Zu Beginn der Datei wird ein weiteres Tool importiert, das später Verwendung findet.
  • Im Konstruktor wird der Konstruktor der Eltern-Klasse aufgerufen. Dies beinhaltet die Initialisierung der standardmäßig eingebundenen TagLibs. Jede TagLib wird in einem Objekt in der Variable $this->__TagLibs nochmals durch ein eigenes Objekt repräsentiert, damit der Parser weiß, auf welche TagLibs er den Inhalt untersuchen muss. Nur bekannt gemachte TagLibs klönnen gefunden werden!
  • In der Methode onParseTime() werden die Tag-Attribute eingelesen und der aktuelle Request-Parameter mit Hilfe der Klasse variablenHandler ermittelt. Anschließend wird mit Hilfe der privaten Funktion __getContent() der Inhalt des Objekts gefüllt. Ist der Inhalt eingelesen, wird versucht, mit den Parser-Methoden __extractTagLibTags() und __extractDocumentController() enthaltene und bekannte Tags und DocumentController zu extrahieren und als Kinder bzw. Attribut einzuhängen.
  • Innerhalb der Methode __getContent() wird lediglich der Inhalt der mit dem Übergabe- Parameter spezifizierten Datei geladen und der Inhalt zurückzugeben. Ist die gewünschte Datei nicht vorhanden wird der Inhalt einer Standard-Fehler-Datei zurückgegeben.
Für weiterführende Anwendungs-Beispiele können die TagLibs für das Formular- Management herangezogen werden. Diese befinden sich im Ordner apps/tools/form/taglib/.


Kommentare

Möchten Sie den Artikel eine Anmerkung hinzufügen, oder haben Sie ergänzende Hinweise? Dann können Sie diese hier einfügen. Die bereits verfassten Anmerkungen und Kommentare finden Sie in der untenstehenden Liste.

«   1   »
Einträge/Seite: | 5 | 10 | 15 | 20 |

1 mcerror
24.05.2008, 17:32:17
Noch ein Hinweis:
Hirarchien von Tags sind immer fest definiert. Für Details siehe: http://forum.adventure-php-framework.org/de/viewtopic.php?f=4&t=38&p=121

Powered by WebRing.