Schachtelung TagLibs

Hier dreht sich alles um die auf der Webseite veröffentlichten Tutorials. // This forum is all about the APF tutorials.
Antworten
mcerror
Beiträge: 19
Registriert: 19.05.2008, 16:20:22

Schachtelung TagLibs

Beitrag von mcerror » 23.05.2008, 17:27:38

Hallo,

im Tutorial auf http://adventure-php-framework.org/Seit ... -erstellen ist ein BEispiel für die Schachtelung von Taglibs angegeben. Warum kann ich nicht in <shop:basket> einfach das Tag <template:getstring> verwenden?

Benutzeravatar
dr.e.
Administrator
Beiträge: 4537
Registriert: 04.11.2007, 16:13:53

Re: Schachtelung TagLibs

Beitrag von dr.e. » 23.05.2008, 19:33:21

Hallo mcerror,

das ist in der Tat eine Einschränkung, jedoch ist diese beabsichtigt. Einerseits aus Konsistenzgründen und andererseits aus Performance-Gründen.

1. Konsistenzgründe:
Die Tag-Hirarchien klar zu definieren heißt, dass die Abhängigkeiten immer klar sind. Oft braucht man von einem bestimmten Tag eine Referenz auf das Vater-Objekt oder umgekehrt um funktionieren zu können (Beispiel: Formular-Tags). Werden die Schachtelungen der Tags ohne diese feste Struktur ausgewertet, so entstehen u.U. Referenzfehler, die zunächst für den Anwender nicht verständlich sind.

2. Performancegründe:
Möchte man die verschiedenen Hirarchieebenen auflösen, so sind je nach Anzahl der in einem Template-File vorkommenden Tags unterschiedlich viele Kombinationsmöglichkeiten der Auflösung möglich. Diese zu evaluieren ist algorithmisch natürlich möglich, kostet aber Rechenzeit. Zusätzlich kommt noch die Auflösung der Abhängigkeiten ins Spiel, die dann auch nochmal Rechenzeit für das Prüfen der Umgebung in Anspruch nehmen.

Aus den genannten Gründen habe ich entschieden, die Implementierung so zu wählen. Möchtest du bestehende Funktionalität innerhalb deiner eigenen Tags verwenden, so ist das recht einfach. Dein Beispiel sieht dann wie folgt aus:

Template-Datei:

Code: Alles auswählen

<shop:basket>
   <basket:getstring />
</shop:basket>
Implementierung Tag <basket:getstring />

Code: Alles auswählen

class basket_taglib_getstring extends template_taglib_getstring
{
}
Durch Vererbung kannst du die Funktionalität vollständig übernehmenm, musst lediglich dafür sorgen, dass es eine Implementierung für das Tag <basket:getstring /> gibt.

Ich hoffe, ich konnte deine Frage damit beantworten.
Viele Grüße,
Christian

mcerror
Beiträge: 19
Registriert: 19.05.2008, 16:20:22

Re: Schachtelung TagLibs

Beitrag von mcerror » 24.05.2008, 17:30:30

Hallo doc,

danke für die Info, habe ich verstanden. Habe auf der Tutorialseite einen KOmmentar geschrieben. Vielleicht hilft es ja jemandem beim Lesen.

MC

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: Schachtelung TagLibs

Beitrag von Screeze » 10.08.2009, 17:09:57

Code: Alles auswählen

<html:form name="registerForm" method="post" action="">
<form:getstring namespace="." config="register_language" entry="form.DERHIERFUNKTIONIERT" />
<form:text name="username" style="width: 300px;" validate="true" button="register_submit" filter="stripTags" />
<form:genericval button="register_submit" field="username">
          <form:getstring namespace="." config="register_language" entry="genval.DERHIERNICHT" />
</form:genericval>
warum funktioniert in gezeigtem beispiel letzteres holen einer sprachenvariable nicht?
Ich versteh da noch nicht ganz die struktur glaub ich... im form selber funktionierts, aber im genericval nicht...

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: Schachtelung TagLibs

Beitrag von MrNiceGuy » 10.08.2009, 19:23:15

Wahrscheinlich, weil du dich innerhalb eines andern TagLibs befindest. Wenn du verschachtelte TagLibs nutzt muss jeder weiter TagLib im "Inneren" bekannt sein oder bekannt gemacht werden. Im Falle form:genericval ist wohl kein form:getstring bekannt.
There are only 10 Types of people in the world:
Those who understand binary and those who don't.


Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: Schachtelung TagLibs

Beitrag von MrNiceGuy » 10.08.2009, 19:29:41

Für manche Tags gibt es addtaglib-TagLibs: http://adventure-php-framework.org/Seit ... -Addtaglib Allerdings kanne es sein, dass für deinen speziellen Fall keines vorhanden ist, dann müsstest du das manuell nachimplementieren. Dazu solltest du dann aber lieber Dr. e fragen, denn ich bin gleich für ein paar Wochen weg. Sorry.
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: Schachtelung TagLibs

Beitrag von Screeze » 10.08.2009, 19:31:43

das mit addtaglib hab ich schon versucht vorhin, sowas in der art dacht ich mir, aber die hats nicht übersetzt, bleibt wohl nur nachrüsten, außer dr.e hat ne bessere lösung

Benutzeravatar
dr.e.
Administrator
Beiträge: 4537
Registriert: 04.11.2007, 16:13:53

Re: Schachtelung TagLibs

Beitrag von dr.e. » 10.08.2009, 21:14:27

Hallo ihr beiden,

wie oben schon angerissen, ist bei der Schachtelung von Taglibs eine strenge Ordnung einzuhalten. Die Gründe habe ich oben dargelegt, andernfalls wäre das APF nicht so schnell.

Nehmen wir das Beispiel von oben:

Code: Alles auswählen

<html:form>
   <form:getstring  />
   <form:text  />
   <form:genericval>
      <form:getstring />
   </form:genericval>
</html:form>
Damit die Tags innerhalb von <html:form /> verarbeitet werden können (dies passiert üblicherweise über den Aufruf von __extractTagLibTags() in der Methode onParseTime()), müssen die zu verarbeitenden TagLibs im Konstruktor der TagLib oder vor dem Aufruf von __extractTagLibTags() bekannt sein. In diesem Fall wird also in de Klasse html_taglib_form etwas in der Art stehen:

Code: Alles auswählen

$this->__TagLibs[] = new TagLib('tools::form::taglib','form','getstring');
$this->__TagLibs[] = new TagLib('tools::form::taglib','form','text');
$this->__TagLibs[] = new TagLib('tools::form::taglib','form','genericval');
Innerhalb der Methode __extractTagLibTags() wird dann der Inhalt eines Tags - in diesem Fall

Code: Alles auswählen

   ...
   <form:text  />
   <form:genericval>
      <form:getstring />
   </form:genericval>
   ...
auf bekannte Tags untersucht. Findet der Parser solche, werden diese als Kinder im aktuellen Knoten erzeugt und dem unter http://adventure-php-framework.org/Seit ... ufdiagramm beschriebenen Lifecycle unterzogen. Sind die Tags nicht bekannt, so werden sie entweder im falschen Kontext oder garnicht geparst.

In diesem Fall ist das Tag <form:getstring /> direkt im Tag <html:form /> bekannt, weshalb es beim ersten Durchlauf des Inhalts des Formulars geparst und dort als Kind eingehangen wird.

Ist ein Tag nicht bekannt, so wird es nicht beachtet und erscheint hinterher als Text im Seiten-Quelltext. Beim Parsen von <form:genericval /> wird der verbleibende Inhalt dann als Inhalt des Tags gesetzt, und bei nicht erfolgreicher Validierung ausgegeben. Da dort effektiv ein Marker der Form <98765435623478900198 /> (die ObjectID als XML-Tag), wird auch keine Meldung im Fehlerfall ausgegeben.

Das bedeutet für den aktuellen Fall: es muss auf die Hirarchie der Tags geachtet werden und falls notwendig durch ein addtaglib die gewünschte TagLib bekannt gemacht werden. Wichtig ist zudem, dass das im im nächst höheren Zweig bekannte Tag nicht schon unterhalb dieses Tags bekannt ist.

Da die Taglibs noch nicht überarbeitet sind, gibt es nun mehrere Lösungsmöglichkeiten:
  • Nutzen der Validator-Gruppe. Mit dieser können sprachabhängige Meldungen ausgegeben werden.
  • Schreiben einer Taglib, die von form_taglib_genericval ableitet, jedoch die Funktion von form_taglib_getstring zur Zeit der Transformation ausführt.
Letztere Möglichkeit halte ich für sinnvoll, denn du kannst die Taglib - einmal geschrieben - per <form:addtaglib /> in jedes deiner Formulare einbinden. Der initiale Aufwand lohnt sich also.

Ich hoffe, das hilft dir/euch weiter.

Viele Grüße,
Christian
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4537
Registriert: 04.11.2007, 16:13:53

Re: Schachtelung TagLibs

Beitrag von dr.e. » 10.08.2009, 21:18:47

Noch ein Wort zu den <*:addtaglib />-Tags:
Diese sind auch "nur" Taglibs und hier nutze ich das Konzept des Parsers aus, der jeden Tag als Kind eines aktuellen Knotens erzeugt. Beim Durchlauf des Parser-Vorgangs eines aktuellen Templates ist es auf Grund des Parsers möglich, ihm weitere Taglibs unterzuschieben. Genau so funktionieren auch die addtaglib-Tags. Sie injizieren in der onParseTime() dem Vater-Objekt eine neue Taglib. Beim nächsten Durchlauf des Parsers ist diese dann bekannt und kann interpretiert werden. Das ist auch der Grund, warum ein <*:addtaglib /> in der Datei vor einer neu bekannt gemachten Taglib stehen muss.

Viele Grüße,
Christian
Viele Grüße,
Christian

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: Schachtelung TagLibs

Beitrag von Screeze » 10.08.2009, 21:28:23

na klar hilft das, sowas in der art hab ich befürchtet :D
Gut dann werd ich das morgen direkt versuchen.

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: Schachtelung TagLibs

Beitrag von Screeze » 19.08.2009, 19:23:52

Nächste Frage:
Hab ich eine möglichkeit den "kindern" eines eigenen taglibs, welche ebenfalls eigene taglibs darstellen, attribute zu übergeben?

bsp:

Code: Alles auswählen

<parent:bla templates="style1/">
     <child:bla .. />
</parent:bla>
Jetzt müsste ich im parent modul die templatedateien auf vorhandensein prüfen, und dann bestimmte dateien ect. dem child übergeben, bevor dieser transformiert wird.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4537
Registriert: 04.11.2007, 16:13:53

Re: Schachtelung TagLibs

Beitrag von dr.e. » 19.08.2009, 20:27:58

Hallo Screeze,

sofern ich dich richtig verstanden habe, möchtest du folgendes tun:

Code: Alles auswählen

class parent_taglib_bla extends Document {

   public function parent_taglib_bla(){
      $this->__TagLibs[] = new TagLib('...','child','bla');
   } 

   public function transform(){
      foreach($this->__Children as $objectId => $DUMMY){
         // übergebe Attribute aus dem aktuellen Knoten an das Kind
         $this->__Children[$objectId]->setAttribute('foo',$this->getAttribute('foo'));
         ...
      }
   }    
}
Alternativ dazu kannst du im Kond-Knoten bei der Transformation auch auf das Attribut des Eltern-Knotens per

Code: Alles auswählen

$this->__ParentObject->getAttribute('foo');
zugreifen. Die beiden Objekte kennen sich also immer über die Vater->Kind und über die Kind->Vater Beziehung. Den Großvater eines Knotens erhälst du damit folgerichtig über

Code: Alles auswählen

$this->__ParentObject->getByReference('ParentObject');
Viele Grüße,
Christian

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: Schachtelung TagLibs

Beitrag von Screeze » 19.08.2009, 22:21:59

Code: Alles auswählen

public function parent_taglib_bla(){
      $this->__TagLibs[] = new TagLib('...','child','bla');
   } 
soweit war ich schon

Code: Alles auswählen

foreach($this->__Children as $objectId => $DUMMY){
         // übergebe Attribute aus dem aktuellen Knoten an das Kind
         $this->__Children[$objectId]->setAttribute('foo',$this->getAttribute('foo'));
         ...
      }
Das ist neu, sieht nach dem aus was ich brauch.
gehe ich richtig der annahme, dass ich so auch auf jede beliebige andere methode, die ich ihm kindelement erstelle, zugriff habe?

Danke

Benutzeravatar
dr.e.
Administrator
Beiträge: 4537
Registriert: 04.11.2007, 16:13:53

Re: Schachtelung TagLibs

Beitrag von dr.e. » 19.08.2009, 23:00:34

Hi,
gehe ich richtig der annahme, dass ich so auch auf jede beliebige andere methode, die ich ihm kindelement erstelle, zugriff habe?
Na klar. Da du in der Schleife Zugriff auf das Objekt hast, kannst du alle öffentlichen Methoden des Objekts nutzen um die Transformation durchzuführen. Dies gilt auch für den umgekehrten Fall - den Zugriff vom Kind auf den Vater. Auch hier kannst du alle öffentlichen Methoden des Vaters nutzen um den gewünschten Effekt zu erziehlen.

Sofern du die API verletzt - sprich eine protected oder private Methode aufrufst - wirst du ohnehin darauf aufmerksam gemacht.
Viele Grüße,
Christian

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast