• Willkommen im Zend Framework Forum

    ZF1 Zend Framework 1 + ZF2 Zend Framework 2

    Das Zend Framework Forum ist seit 2006 die erste Anlaufstelle für Zend Framework Entwickler in Deutschland. Mit über 70.000 Beiträgen und einer steigenden Nutzerzahl bietet das Forum hilfreiche Themen und ZF-Tutorials für professionelle Entwickler, fortgeschrittene Programmierer sowie Zend Framework Einsteiger.
    Wenn dies Dein erster Besuch in der Zend Framework Community ist, lies bitte zuerst die Hilfe - FAQ durch. Du musst Dich registrieren, bevor Du Beiträge verfassen kannst. Klicke oben auf 'Registrieren', um die Registrierung zu starten. Du kannst auch jetzt schon Beiträge lesen. Hier im Forum findest Du die Zend Framework Hilfe, die Du suchst!

    Grüße an alle Zend Framework Entwickler. Das Team vom Zend Framework Forum!

    Drupal Agentur

Kombination mit Zend_Form ViewScript Dekoratioren und DisplayGroup ViewScript Dekorat

Oliver Kühne

New member
Hallo,

ich hoffe der Titel ist nicht verwirrend, aber ich wusste nicht wie ich mein Problem besser in einer Überschrift umschreiben soll.

Folgendes Szenario:
Ich habe eine Zend_Form wo ich ein ViewScript setze sowie einzelne Elemente die widerum ein eigenes ViewScript nutzen:

PHP:
class My_Form_Login extends Zend_Form {
    public function init() {
        $this->setDecorators(
                    array(
                        array(
                            'ViewScript',
                            array(
                                'viewScript' => '_forms/login.phtml',
                            )
                        )
                    )
            );

        $user = new My_Form_Element_Login_Text('username');
        $user->setLabel("Benutzername");
    }  
}
My_Form_Element_Login_Text:
PHP:
class My_Form_Element_Login_Text extends Zend_Form_Element_Text {
    public function __construct($options = null) {
        parent::__construct($options);

    }     
    public function loadDefaultDecorators() {
               $this->setDecorators(array(
                    array(
                'ViewScript',
                array(
                    'viewScript' => '_forms/element/login/text.phtml',
                )
            )
        ));
    }
}
_forms/login.phtml:
HTML:
<form action="<?php echo $this->element->getAction(); ?>" method="<?php echo $this->element->getMethod(); ?>">
    
    <h3 class="form-title">Login in dein Account</h3>
    <?php
    foreach ($this->element->getElements() as $element) {
        echo $element;
    }
    ?> 
</form>
Soweit funktioniert das alles wirklich wunderbar, das HTML wird so angezeigt wie ich das will. Aber sobald ich eine DisplayGroup hinzufüge (in My_Form_Login) und diesem ein ViewScript zuweise, wird dieses nicht korrekt angezeigt:

PHP:
class My_Form_Login extends Zend_Form {
    public function __construct($options = null) {
        parent::__construct($options);
    }  
    
    public function init() {

        $this->setMethod('post');
        $this->setAction("");
        $this->setDecorators(
                    array(
                        array(
                            'ViewScript',
                            array(
                                'viewScript' => '_forms/login.phtml',
                            )
                        )
                    )
            );
        
        
        $user = new My_Form_Element_Login_Text('username');
        $user->setLabel("Benutzername");
        $pass = new My_Form_Element_Login_Password('password');
        $pass->setLabel('Passwort');
        
        
        $checkbox = new My_Form_Element_Login_Checkbox('remember');
        $checkbox->setLabel('Remember me');
        $button = new My_Form_Element_Login_Button('login');
        $button->setLabel('Login');
        
        
        
        
        $this->addElements(array($user, $pass));
        
 
        
        $this->addDisplayGroup(array($checkbox, $button), 'formactions');
        
        $group = $this->getDisplayGroup('formactions');
            $group->setDecorators(
                    array(
                        array(
                            'ViewScript',
                            array(
                                'viewScript' => '_forms/element/login/group-form-actions.phtml',
                            )
                        )
                    )
            );

    }
}
_forms/element/login/group-form-actions.phtml:
HTML:
<div class="form-actions">
    <?php
    $elements = $this->element->getElements();
    foreach ($elements as $element) {
        echo $element;
    }
    ?>
</div>
Die Elemente ($checkbox und $button) werden korrekt mit ViewScript übergeben aber das HTML ("<div class="form-actions">..</div>") was die DisplayGroup umschließen soll nicht. Entferne ich nun in der Zend_Form das ViewScript, dann habe ich die gewünschte anzeige der DisplayGroup. Soll heißen, dass eine geht hier scheinbar nicht zusammen mit dem anderen und ich teste und suche schon eine ganze Zeit wie ich dieses Problem umgehen kann, nur leider finde ich keine Hilfe.

Noch mal Zusammengefasst:
Zend_Form + ViewScript = (ok) und DisplayGroup + ViewScript (nur Elemente kein HTML Container)

Zend_Form ohne ViewScript und DisplayGroup + ViewScript (HTML Elemente werden korrekt für die DisplayGroup angezeigt)

Ich hoffe ich konnte einigermaßen verständlich mein Problem schildern und vielleicht hat ja hier jemand einen Vorschlag der mein Problem löst.

Vielen Dank
Oliver
 

Kaiuwe

Super-Moderator
Willkommen im Forum! :)

Ich will mal nur an dieser Stelle einhaken, denn dies fiel mir gleich ins Auge:
_forms/login.phtml:
HTML:
<form action="<?php echo $this->element->getAction(); ?>" method="<?php echo $this->element->getMethod(); ?>">
    
    <h3 class="form-title">Login in dein Account</h3>
    <?php
    foreach ($this->element->getElements() as $element) {
        echo $element;
    }
    ?> 
</form>
Passend dazu gibt es ein Element und hier im Forum auch eine Beschreibung dazu. Damit wird das „View“-Skript für das Formular überflüssig.
 

Kaiuwe

Super-Moderator
My_Form_Element_Login_Text:
PHP:
class My_Form_Element_Login_Text extends Zend_Form_Element_Text {
    public function __construct($options = null) {
        parent::__construct($options);

    }     
    public function loadDefaultDecorators() {
               $this->setDecorators(array(
                    array(
                'ViewScript',
                array(
                    'viewScript' => '_forms/element/login/text.phtml',
                )
            )
        ));
    }
}
Schlechte Idee, denn damit ziehst du das Element auf genau ein bestimmtes „View“-Skript fest. Bei einem nächsten Projekt oder einem anderen Formular kannst du das Element nicht mehr verwenden.
Wenn du ein „View“-Skript verwenden möchtest, dann reicht es, wenn du die Zuweisung in der Formularklasse vornimmst.
 

Oliver Kühne

New member
Hallo Kaiuwe und danke für die Antwort,

Deine Lösung würde funktionieren, gar keine Frage. Aber so erreiche ich es eigentlich, dass ich HTML Elemente direkt in den Code schreibe. Wenn bei uns jemand das Template anpassen will muss er immer direkt an den Code, was ich eigentlich vermeiden wollte. Ich wollte alles was wirklich HTML Elemente sind auslagern in eigene .phtml Dateien. Deswegen wäre die Lösung die du vorgeschlagen hast, für meine Zwecke nur ein Workaround mit dem ich mein eigenes Konzept ja umgehe.

Gruß Oliver
 

Kaiuwe

Super-Moderator
Wenn bei uns jemand das Template anpassen will muss er immer direkt an den Code, was ich eigentlich vermeiden wollte.
Die Idee mit der gesonderten Klasse „My_Form_Element_Login_Text“ bleibt auch dann weiterhin schlecht.

Ich wollte alles was wirklich HTML Elemente sind auslagern in eigene .phtml Dateien.
Nimm ZF2, wenn es nicht ein altes und gewachsenes Projekt ist. :D


Nachtrag:
Da ist ja noch mehr: „My_Form_Element_Login_Checkbox“, „My_Form_Element_Login_Password“ und „My_Form_Element_Login_Button“.
10 Formulare mit jeweils 10 Elementen sind dann…genau, ein großer Haufen an Klassen, welche gepflegt werden müssen.
 
Zuletzt bearbeitet:

Oliver Kühne

New member
Die Idee mit der gesonderten Klasse „My_Form_Element_Login_Text“ bleibt auch dann weiterhin schlecht.


Nimm ZF2, wenn es nicht ein altes und gewachsenes Projekt ist. :D


Nachtrag:
Da ist ja noch mehr: „My_Form_Element_Login_Checkbox“, „My_Form_Element_Login_Password“ und „My_Form_Element_Login_Button“.
10 Formulare mit jeweils 10 Elementen sind dann…genau, ein großer Haufen an Klassen, welche gepflegt werden müssen.
10 Formulare mit jeweils 10 Elementen
Hmm eigentlich nicht...
Form1:
PHP:
$checkbox = new My_Form_Element_Login_Checkbox();
Form2:
PHP:
$checkbox = new My_Form_Element_Login_Checkbox();
...

Form10:
PHP:
$checkbox = new My_Form_Element_Login_Checkbox();
Oder übersehe ich da was?

Ja, das sehe ich ein, dass könnte man auch direkt in der Form, wie du beschrieben hast lösen, dass wäre möglich. Meine Idee dahinter war, dass wenn ich ein weiteres Formular erstelle den Aufruf spare:

PHP:
       $user = new Zend_Form_Element_Login_Text('username');
       $user->setLabel("Benutzername");
       $user->setDecorators(array(
                    array(
                'ViewScript',
                array(
                    'viewScript' => '_forms/element/login/text.phtml',
                )
            )
        ));
Gut, dass kann man wirklich anders und auch besser lösen, keine Frage :) Aber noch immer habe ich mein Problem welches ich oben beschrieben hab. ZF2 kann ich leider nicht verwenden, der Hauptgrund ist, dass das Projekt im Grunde schon viel zu groß ist um es jetzt zu änderen. Auch haben wir momentan nicht die Ressourcen um das zu bewerkstelligen.

Gruß Oliver

Gruß Oliver
 

Kaiuwe

Super-Moderator
Oder übersehe ich da was?
Wenn du 10 Login-Formulare hast, dann passt es. ;)

Meine Idee dahinter war, dass wenn ich ein weiteres Formular erstelle den Aufruf spare:
Ich denke mal laut: Es müsste ausreichen, wenn du den Konstruktor von „Zend_Form“ erweiterst, dass zuerst das Formular erstellt wird und dann der Dekorierer „ViewScript“ automatisch mit den entsprechenden Pfadangaben zugewiesen wird.

Pseudo-Code:
PHP:
public function __construct($options = null)
{
    parent::__construct($options);

    // Pfad zusammenstellen
    …
    // Dekorierer für Formular, Elemente und Anzeigegruppen zuweisen
    …
}
Man müsste noch Parameter mitgeben, welches Verzeichnis verwendet werden soll.

Beispiel:
Code:
/application/modules/default/views/scripts/forms/auth/login
Mit Fallback auf:
Code:
/application/views/scripts/forms/

Aber noch immer habe ich mein Problem welches ich oben beschrieben hab.
Einen Fehler kann ich leider in deinem Skript momentan nicht sehen. Was sagt der Debugger?

Nachtrag:
Ich erinnere mich dunkel, da war etwas mit Schlüsseln in den Arrays für die Dekorierer.
 
Zuletzt bearbeitet:

Kaiuwe

Super-Moderator
Hier liegt der Fehler
_forms/login.phtml:
PHP:
<form action="<?php echo $this->element->getAction(); ?>" method="<?php echo $this->element->getMethod(); ?>">
    
    <h3 class="form-title">Login in dein Account</h3>
    <?php
    foreach ($this->element->getElements() as $element) {
        echo $element;
    }
    ?> 
</form>
Du holst hier nur die Elemente, aber alles andere lässt du weg. Somit kann auch keine Anzeigegruppe („DisplayGroup“) ausgegeben werden.
Siehe dazu den Dekorierer „Zend_Form_Decorator_FormElements“.
 

Oliver Kühne

New member
Hier liegt der Fehler

Du holst hier nur die Elemente, aber alles andere lässt du weg. Somit kann auch keine Anzeigegruppe („DisplayGroup“) ausgegeben werden.
Siehe dazu den Dekorierer „Zend_Form_Decorator_FormElements“.
Könntest du mir kurz eine Hilfstellung geben, ich stehe da irgendwie auf dem Schlauch. Wie bekomme ich es denn hin, dass ich die DisplayGroup auch im viewScript des Formulars habe?
 

Kaiuwe

Super-Moderator
Könntest du mir kurz eine Hilfstellung geben, ich stehe da irgendwie auf dem Schlauch. Wie bekomme ich es denn hin, dass ich die DisplayGroup auch im viewScript des Formulars habe?
Du musst alle Elemente mit dem Dekorierer „FormElements“ rendern lassen, dann per „ViewScript“-Dekorierer ausgeben:

PHP:
$form->setDecorators(array(
    array('FormElements'),
    array('ViewScript', array('viewScript' => 'foo.phtml', 'placement' => false)),
));
Entscheidend ist die Angabe „placement“, denn ansonsten würde der zuvor erstellte Inhalt vom Dekorierer „FormElements“ einfach davor gesetzt. So erfolgt gar keine Ausgabe des Inhalts.

„foo.phtml“
PHP:
<form action="<?= $this->form->getAction() ?>" method="<?= $this->form->getMethod() ?>">
    <?= $this->content ?>
</form>
Da der „ViewScript“-Dekorierer den zuvor erstellten Inhalt vom Dekorierer „FormElements“ als Variable mit an den „Partial-View“-Helfer weiterreicht, steht der Inhalt ganz einfach zur Verfügung.

Steht alles so im Quellcode:

 

Oliver Kühne

New member
HeyKaiuwe,

danke für deine Hilfe, dank dir hab ich noch ein paar Sachen angepasst. Mein oben beschriebenen Fehlern hat sich folgendermaßen gelößt, so dass er genau das macht was ich will. Ich sag nur "Ockhams Rasiermesser" manchmal ist es dieeinfachste Lösung;
PHP:
<form action="<?php echo $this->element->getAction(); ?>" method="<?php echo $this->element->getMethod(); ?>">
    
    <h3 class="form-title">Login in dein Account</h3>
    <?php
    foreach ($this->element as $element) {
       echo $element;
    }

    ?> 
</form>
Ich hab einfach die Methode "getElements"
PHP:
    foreach ($this->element->getElements() as $element) {
       echo $element;
    }
weg gelassen

PHP:
    foreach ($this->element as $element) {
       echo $element;
    }
Und schon hatte ich genau das Ergebnis was ich erwartet habe. Dennoch danke für deine Hilfe und deine Ratschläge werde ich auf jeden Fall berücksichtigen.

Gruß Oliver
 

Kaiuwe

Super-Moderator
Ich hab einfach die Methode "getElements"
PHP:
    foreach ($this->element->getElements() as $element) {
       echo $element;
    }
weg gelassen

PHP:
    foreach ($this->element as $element) {
       echo $element;
    }
Und schon hatte ich genau das Ergebnis was ich erwartet habe. Dennoch danke für deine Hilfe und deine Ratschläge werde ich auf jeden Fall berücksichtigen.
Darum! ;)
 
Oben