Zum Inhalt springen

eigener For-ViewHelper ohne each-Array

Erstellt am 14. April 2013 · 8 Antworten · letzte Antwort am 27. Juni 2013

Tags: Frage

harald1972 ·

Hallo Leute,

bei den ganzen Fluid-ViewHelpern vermisse ich einen FOR-ViewHelper.
Es gibt zwar einen, der so heißt, aber eigentlich ist das ja ein FOREACH-ViewHelper.
Die Parameter $each und $as sind zwingend vorgesehen.

Ich möchte aber gern einen ViewHelper, der in etwas so aufgerufen werden soll:

<my:customFor init="1" max="10" step="1" as="x" >
  do_something_with{x} 
</my:customFor>

Dabei soll x nur integer-Werte von (in diesem Beispiel) 1 bis 10 annehmen.
Ich möchte also nicht über ein Array iterieren. Weil ich aber zwingend eins haben soll, erzeuge ich eben ein Array = {1,2,3,4,...}
Ich denke, sowas könnte nützlich sein, und ich wundere mich echt, daß es sowas noch nicht gibt. 8-)
Ich hab dazu den Tx_Fluid_ViewHelpers_ForViewHelper genommen und davon folgendes abgeleitet:

class Tx_Myextension_ViewHelpers_CustomForViewHelper extends Tx_Fluid_ViewHelpers_ForViewHelper {
 
  public function initializeArguments() {
		parent::initializeArguments();
		$this->registerArgument('init', 'integer', 0, FALSE, 0);
		$this->registerArgument('max', 'integer', 0, FALSE, 0);
		$this->registerArgument('step', 'integer', 0, FALSE, 1);
	} 
	
  /**
   * the render method
   *
   * @param string $as 
   * @param string $key
   * @param boolean $reverse 
   * @param string $iteration
   * @return string 
   */
  public function render($as, $key='', $reverse=FALSE, $iteration=NULL) {
    $each = array();
    for($i= intval($this->arguments['init']); $i<=intval($this->arguments['max']); $i+=intval($this->arguments['step'])){
      $each[$i]=$i;
    } 
    parent::render($each, $as, $key, $reverse, $iteration);     
  }    
}

Soviel zu meinem Ansatz.
Nur funktioniert das so nicht.
Vielleicht sieht ja jemand, wo hier mein Denkfehler ist.
Ich hab schon einiges ausprobiert, komm aber nicht auf die Lösung. 😢

harald1972 ·

Klingt so trivial wie logisch...

kainobi schrieb

Ich glaube Du musst

return parent::render($each, $as, $key, $reverse, $iteration);

schreiben.

hilft mir aber nicht 🙁
Ich bekomm nichts gerendert.

Ich hab jetzt testweise mal einen alert in die render-Methode gesetzt, um mir mein $each ausgeben zu lassen.
Das Array sieht eigentlich ganz genau so aus, wie es sein soll (zumindest denk ich, daß es so sein soll), also {1=>1, 2=>2,...}

Dabei taucht aber noch ein Punkt auf, den ich nicht verstehe:
Der alert wird nur ausgelöst, wenn ich den cache geleert habe. Ohne den cache zu leeren, wird beim Neuladen der ViewHelper nicht angestossen - wenigstens wird kein alert ausgelöst.

harald1972 ·

Das mit der cacheable action hab ich mir auch schon mal gedacht.
Ich hab meinen Test (mit dem alert) gleich in die list-action von meiner Aggregatwurzel.
Und die hab ich bei den non-cacheable actions drin... extra deswegen.
Trotzdem wird der alert nur ausgelöst, nachdem ich den cache geleert habe.

Aber das ist ja eigentlich gar nicht mein Problem - ich denke auch nicht, daß es damit zu tun hat.
#paralyzed# ...naja, wer weiß... #evil#

harald1972 ·

Da bin ich wieder, zwar nicht sonderlich schlauer oder irgendwie weiter, aber ich hab nochmal was festgestellt.

Ich hab spaßeshalber mal folgendes ausprobiert:
Die render-Methode um $each erweitert, also die selben Params wie parent-Klasse

public function render($each, $as, $key='', $reverse=FALSE, $iteration=NULL) {    
    for($i= intval($this->arguments['init']); $i<=intval($this->arguments['max']); $i+=intval($this->arguments['step'])){
      $each[$i] = $i;   
    }
     
    foreach($each as $key => $val){ 
        $this->alert($key.'=>'.$val); }
    
    return parent::render($each, $as, $key, $reverse, $iteration);     
  }

($this-alert() sorgt für javascript-alert)
und dieses fluid/html-code

<my:customFor each="{0:0}" init="1" max="5" step="1" as="y" key="x">
<p> {x}: {y} </p>
</my:customFor>

Ich gebe also ein 0-Element im each-array mit (wodurch bestenfalls 1 Element zuviel erzeugt wird).
Ich bekomme (korrekt) den alert von 0 bis 5.
Gerendert wird aber nur

0: 0

#evil#

harald1972 ·

So! 🙂🙂🙂

Jetzt hab ich's !

Wer also gern einen For-ViewHelper ohne zwingendes each-Array haben will, kanns gern verwenden.

  /**
   * the render method
   *         
   * @param string $as The name of the iteration variable
   * @param string $key The name of the variable to store the current array key
   * @param boolean $reverse If enabled, the iterator will start with the last element and proceed reversely
   * @param string $iteration The name of the variable to store iteration information (index, cycle, isFirst, isLast, isEven, isOdd)
   * @return string Rendered string
   */
  public function render( $as, $key='', $reverse=FALSE, $iteration=NULL) {    
    for($i= intval($this->arguments['init']); $i<=intval($this->arguments['max']); $i+=intval($this->arguments['step'])){
          $this->arguments['each'][$i] = $i;      
    }    
    return parent::render($this->arguments['each'], $as, $key, $reverse, $iteration);     
  }

Anstatt $each als Parameter zu übergeben, verwende ich $this->arguments['each']
Obwohl ich es nicht in der Argumentliste hab, hab ich es vom parent geerbt und beschreibe dieses Array einfach, wie es mir passt :p

Nachtrag: da war ein Tippfehler. Da stand...

    return parent::render($this->arguments['$each'], $as, $key, $reverse, $iteration);

... seltsamerweise hat es trotzdem funktioniert :o

harald1972 ·

Okay,

1. Glaub mir: ich hab wie besessen gesucht und nichts gefunden.

2. Die Links tun bei mir nicht (es fehlt der Doppelpunkt hinter http, wenn ich draufklick)

3. Ich habs mir trotzdem angeschaut. 😉 folgende Unterschiede hab ich festgestellt:
Max Kalus geht den Weg über templateVariableContainer add und remove.
Imho geschieht das aber in der parent::render.
Deswegen ist parent::render, die einzige Methode, die ich aufrufen muss.
Die Variable "variable" oder "variableName" ist auch redundant, weil "as" schon definiert ist.
Ich verwende $this->arguments[...], Max Kalus nicht.
Den Unterschied im letzten Punkt hab ich selbst nicht genau verstanden.

Harald