PHP Sammelthread: Zend Framework und alles was dazugehört

Hallo,

ich versuche mich gerade daran, ein Menü aufzubauen und nutze dafür Zend_Navigation.
Nun möchte ich gerne dem aktiven Link eine CSS-Klasse zugewiesen wird.

Meine Dateien sehen wie folgt aus:

navigation.phtml
PHP:
echo '<ul>';
foreach ($this->container as $page) {
    echo '<li>' . $this->menu()->htmlify($page) . '</li>', PHP_EOL;
}
echo '</ul>';

layout.phtml
PHP:
[..]
$this->navigation()->menu()->setPartial(array('navigation.phtml','default'));
echo $this->navigation()->menu(); 
[..]

Ausgabe:
PHP:
<ul>
    <li><a href="index">Start</a></li>
    <li><a href="auth">test1</a></li>
</ul>

Hätte aber gerne
PHP:
<ul>
    <li><a href="index">Start</a></li>
    <li class="myClass"><a href="auth">test1</a></li> <-- wenn das angeklickt wurde
</ul>

Hat jemand eine Idee?

Gruß
DadyCool
 
Hmm,

es funktioniert schon ganz gut, nur packt er die css-Klasse in den
PHP:
<a href
ich hätte diese gerne im
PHP:
<li>
tag.

Eine Idee wie das funktioniert?

Gruß
DadyCool


EDIT:

Ich habe das nun wie folgt gelöst:




Plugin: Instanziert mir die Zend Navigation

PHP:
class Plugins_Menu extends Zend_Controller_Plugin_Abstract
{
    public function routeShutdown(Zend_Controller_Request_Abstract $request)
    {
 
        $viewRenderer = Zend_Controller_Action_HelperBroker::getExistingHelper('ViewRenderer');
        $viewRenderer->initView();
        $view = $viewRenderer->view;
        
         $container = new Zend_Navigation(array(
                    'Overview' => array(
                        'label' => 'Overview',
                        'type' => 'uri',
                        'uri' => 'index'
                    ),
              'Template' => array(
                        'label' => 'Template',
                        'type' => 'uri',
                        'uri' => 'auth'
                    ),
            
              'Sample Page' => array(
                        'label' => 'Sample Page',
                        'type' => 'uri',
                        'uri' => 'https://example.com'
                    ),
            
              'Logo Images' => array(
                        'label' => 'Logo Images',
                        'type' => 'uri',
                        'uri' => 'https://example.com'
                    ),
            
            
            
            
            
                ));
        $view->navigation($container);


im layout.phtml Script:
PHP:
$this->navigation()->menu()->setPartial(array('navigation.phtml','default'));
echo $this->navigation()->menu();

Mein Navigation.phtml Script:
PHP:
/**
 * Funktion zeigt das submenu an (rekrusiv)
 * @param type $subPage 
 * @param type $object 
 */
function submenu($subPage, &$object) {

    $ulTagStart = true;
    foreach ($subPage as $sub) {
        if ($ulTagStart)
            echo "<ul>";
        $ulTagStart = false;
        $isActive = $sub->isActive(false);
        $liSubClass = $isActive ? ' class="highlight"' : '';

        echo '<li' . $liSubClass . '>' . $object->menu()->htmlify($sub) . '</li>', PHP_EOL;
        if ($sub->isActive(true)) {
            submenu($sub->getPages(), &$object);
        }
    }
    if (!$ulTagStart)
        echo "</ul>";
}

// Hauptmenu anzeigen
echo '<ul>';
foreach ($this->container as $page) {
    $isActive = $page->isActive(false);
    $liClass = $isActive ? ' class="highlight"' : '';
    echo '<li ' . $liClass . '>' . $this->menu()->htmlify($page) . '</li>', PHP_EOL;


    if ($page->isActive(true)) {
        // Submenu anzeigen
        submenu($page->getPages(), &$this);
    }
}

echo '</ul>';


Was sagt ihr zu der Lösung?

Mfg
DadyCool
 
Zuletzt bearbeitet:
Hmm,

ich habe eine Form Klasse:
login.php
PHP:
<?php

class Application_Form_Login extends Zend_Form {

    public function init() {
        $this->setName("login");
        $this->setMethod('post');
        $this->setDecorators(array(array('viewScript', array('viewScript' => 'form.phtml'))));

      
        $this->addElement('text', 'username', array(
            'filters' => array('StringTrim', 'StringToLower'),
            'validators' => array(
                array('StringLength', false, array(0, 50)),
                array('NotEmpty', true, array('messages' => array('isEmpty' => 'Username wird benötigt')))
            ),
            'required' => true,
            'label' => 'Username:',

            
        ));

        $this->addElement('password', 'password', array(
            'filters' => array('StringTrim'),
            'validators' => array(
                array('StringLength', false, array(0, 50)),
                array('NotEmpty', true, array('messages' => array('isEmpty' => 'Password wird benötigt')))
            ),
            'required' => true,
            'label' => 'Password:',
        ));

        $this->addElement('submit', 'login', array(
            'required' => false,
            'ignore' => true,
            'label' => 'Login',
        ));

        // CSRF Protektion hinzufügen
        $this->addElement('hash', 'csrf', array(
            'ignore' => true,
        ));
    }

}

diese wird im LoginController instanziiert
PHP:
    public function indexAction()
    {
        $form = new Application_Form_Login();
  
        $request = $this->getRequest();
        if ($request->isPost()) {
            if ($form->isValid($request->getPost())) {
                if ($this->_process($form->getValues())) {
                    // We're authenticated! Redirect to the home page
                    $this->view->passedAuthentication = true;
                    $this->_helper->redirector('index', 'index');
                }
            }
        }
        $this->view->form = $form;
    }


Ich dachte eigentlich, das ich auf die einzelnen Elemente so Zugriff bekomme:
PHP:
$this->form->username

jedoch funktioniert dies nicht. Wenn ich mir $this->form mit var_dump anschaue ist es auch NULL

Wie kann ich nun im ViewScript (form.phtml) auf die einzelnen Elemente des Formulars zugreifen?

Danke

Edit:
Glaube es hat sich erledigt :)
scheint mit $this->element zu gehen :)


Mfg
DadyCool
 
Zuletzt bearbeitet:
PHP:
$form->getValue('username')



Aber warum willst du im View-Script darauf zugreifen? Mach ein echo des Formulars ;)
PHP:
echo $form
 
Schonmal probiert das rein über CSS anzupassen? geht wunderbar.
Schau dir alternativ die Decoratoren von Zend_Form an, dann kannst du weiterhin mit echo dein Formular ausgeben, hast aber deinen Markup.

Ich würde aber stark dazu raten den Orignial-Markup zu lassen, über CSS sollte es komplett anpassbar sein, wie du es gerne hättest.
 
Hallo Leute,

nachdem ich eine ganze Zeit rumgespielt habe, sieht mein Formular endlich so aus wie ich es haben möchte:

PHP:
<form id="login" enctype="application/x-www-form-urlencoded" method="post" class="form" action="/4develop/public/login">
    <label for="username" class="required">Username:</label>
    <div class="div_texbox">
        <input type="text" name="username" id="username" value="" class="username" />
    </div>
    <label for="password" class="required">Password:</label>

    <div class="div_texbox">
        <input type="password" name="password" id="password" value="" class="password" />
    </div>
    <div class="button_div">
        <input type="submit" name="login" id="login" value="Login" class="buttons" />
    </div>
    <div>
        <input type="hidden" name="csrf" value="f7cc02562b4b9c23ef72d2c02eefe594" id="csrf" />
    </div>
</form>



Wie kann ich denn nun die Fehlermeldungen formatieren? Aktuell macht er sowas

PHP:
[...]
<input name="username" id="username" value="" class="username" type="text">
<ul class="errors"><li>Username wird benötigt</li></ul>

wird gerne aber nur ein div haben wollen
PHP:
[...]
<div class="errors">Username wird benötigt</div>

Hier ist meine Klasse,

PHP:
class Application_Form_Login extends Zend_Form {

    public $elementDecorators = array(
        'ViewHelper',
        'Description',
        'Errors',
        array('HtmlTag', array('tag' => 'div', 'class' => 'div_texbox')),
        array('Label'),
    );
    public $elementHidden = array(
        'ViewHelper',
        'Description',
        'Errors',
        array('Label'),
        array('HtmlTag'),
    );
    public $buttonDecorators = array(
        'ViewHelper',
        'Description',
        'Errors',
        array('HtmlTag', array('tag' => 'div', 'class' => 'button_div')),
    );

    public function init() {
        $this->setName("login");
        $this->setMethod('post');
        $this->addAttribs(array('class' => 'form'));
        $this->setDecorators(array(
            'FormElements',
            'Form'
        ));


        $this->addElement('text', 'username', array(
            'filters' => array('StringTrim', 'StringToLower'),
            'validators' => array(
                array('StringLength', false, array(0, 50)),
                array('NotEmpty', true, array('messages' => array('isEmpty' => 'Username wird benötigt')))
            ),
            'required' => true,
            'decorators' => $this->elementDecorators,
            'class' => 'username',
            'label' => 'Username:',
        ));

        $this->addElement('password', 'password', array(
            'filters' => array('StringTrim'),
            'validators' => array(
                array('StringLength', false, array(0, 50)),
                array('NotEmpty', true, array('messages' => array('isEmpty' => 'Password wird benötigt')))
            ),
            'required' => true,
            'decorators' => $this->elementDecorators,
            'class' => 'password',
            'label' => 'Password:',
        ));

        $this->addElement('submit', 'login', array(
            'required' => false,
            'ignore' => true,
            'decorators' => $this->buttonDecorators,
            'label' => 'Login',
            'class' => 'buttons',
        ));

        // CSRF Protektion hinzufügen
        $this->addElement('hash', 'csrf', array(
            'decorators' => $this->elementHidden,
            'ignore' => true,
        ));
    }

}

Danke schonmal :)

mfg
DadyCool
 
Schon gesehen, dass du global Dektoratoren für Elemente festlegen kannst?
PHP:
$this->setElementDecorators(array(
  'ViewHelper',
  'Errors',
  array(
    'decorator' => array('xxx' => 'HtmlTag'),
    'options' => array('tag' => 'xxx')
  ),
  array('Label', array('tag' => 'xxx')),
  array(
    'decorator' => array('xxx' => 'HtmlTag'),
    'options' => array('tag' => 'xxx')
  )
));

Das sollte dein Problem lösen, vor allem brauchst du keine extra Klasse für jeden Typ*, dein Formular ist eben absolut umständlich spezifiziert.
Warum brauchst du überhaupt diese Div-Suppe? Also wie soll es aussehen (Screenshost)?
Der Error-Decorator ließe sich über die Methode genauso festlegen.

Jetzt frag mich aber nicht wo ich den Code herhabe :biggrin:
Ich suche nochmal, vllt finde ich es.


Also wie gesagt, ich finde dein Markup des Formulars sieht unnötig komplex aus, womit du dir das leben mit Zend_Form nur unnötig schwer machst. Die Definitionsliste ist zugegebenerweise auch die semantischste Lösung gegenüber einer Div-Suppe.

Nachtrag:
Bei devzone.zend.com gibt es einen großen Artikel über die Dekoratoren und wie man den Markup anpasst: Decorators with Zend_Form

Nachtrag2:
damit nur ein Fehler angezeigt wird, musst du in deinem Formular bei dem Hinzufügen von Validatoren das "breakChainOnFailure"-Flag setzen, dann wird die Validierung eines Elementes nach dem ersten Fehler abgebrochen.
 
Zuletzt bearbeitet:
Hi,

das Formular sieht so aus :)



Mit dem global Dektoratoren habe ich auch schon rumgespielt, (weiß grade nicht welches Problem ich da hatte).

Ich muss zugeben, das ich das ganze Prinzip mit den Dektoratoren noch nicht durchblickt habe. Z.B weiß ich nicht, was die Angaben überhaupt bewirken
PHP:
'ViewHelper',
        'Description',
        'Errors',

Danke für deine Hilfe (Ich glaube ich muss einfach noch mehr lesen, finde die Zend Referenz aber nicht besonders gut)

Mfg
DadyCool
 
das sollte mit den Standard-Dekoratoren genauso darstellbar sein ;)
Bis auf die grauen Hintergründe und die Grafik in der Textbox sieht es bei mir genauso aus.

Ich muss zugeben, das ich das ganze Prinzip mit den Dektoratoren noch nicht durchblickt habe. Z.B weiß ich nicht, was die Angaben überhaupt bewirken
PHP:
'ViewHelper',
        'Description',
        'Errors',
das sind alles Dekoratoren, die einen Teil des Formulars ausgeben ;)

Danke für deine Hilfe (Ich glaube ich muss einfach noch mehr lesen, finde die Zend Referenz aber nicht besonders gut)
lies mal den von mir verlinkten Artikel im Nachtrag ;)
Also die Dokumentation des Zend Frameworks ist schon verdammt gut, aber Zend_Form ist mit den Dekoratoren eben sowas von komplex, das man da viel Zeit braucht, um das vollständig zu verstehen. Ich habe es bis heute nicht :LOL:
Ich nehme einfach den Standard-Ouput und style den über CSS, dann hab ich kein Stress da erst großartig den ganzen Markup anpassen zu müssen :biggrin:

Folgendes ist alles was ich bei Zend_Form einstelle, die Sub-Klassen definieren dann nur noch die Elemente und deren Validatoren:
PHP:
<?php

/**
 * abstraktes Formular mit Voreinstellungen
 * 
 * @author Tobias Petry (www.petry-newmedia.de)
 */
abstract class App_Form_Abstract extends Zend_Form {
	/**
	 * Initialisierung einer Grundkonfiguration
	 */
	public final function init() {
		// add validators
		$this->addElementPrefixPath('App_Validate','App/Validate/','validate'); 
		
		// add xss-protection
		$this->addElement('hash', 'csrf_protection', array('salt' => 'xxxx')); 
		
		// start form init
		$this->postInit();
		
		// trim all values
		foreach ($this->getElements() as $element) {
			$element->addFilter('StringTrim');
			if($element->getDecorator('label') != false) {
				$element->getDecorator('label')->setRequiredSuffix('*');
			}
        }
		
	}
	
	/**
	 * Inititialsierung der Formularelemente durch Kindklasse
	 */
	public abstract function postInit();
}

Jede Klasse erbt dann von meinem AbstractForm und deklariert alle Elemente in der postInit().
 
Zuletzt bearbeitet:
Danke werde mir den Artikel nochmal genau durchlesen :)
Werde mich sicherlich das eine oder andere Mal hier noch zu Wort melden, für heute mache ich aber erstmal Pause :biggrin:

Danke für deine schnelle Hilfe

Mfg
DadyCool
 
Hmm so ganz raffe ich das noch nicht...
Also es gib die Standard Decoratoren...
https://framework.zend.com/manual/de/learning.form.decorators.layering.html

Jeden der Decoratoren können auch Optionen im Form eines Array übergeben werden.
Was ich nun nicht verstehe:

Entspricht:
PHP:
$this->setElementDecorators(array(
  'ViewHelper',
  'Errors',
  array(
    'decorator' => array('xxx' => 'HtmlTag'),
    'options' => array('tag' => 'xxx')
  ),
  array('Label', array('tag' => 'xxx')),
  array(
    'decorator' => array('xxx' => 'HtmlTag'),
    'options' => array('tag' => 'xxx')
  )
));

eigentlich dem?
PHP:
$this->setElementDecorators(array(
// Dem ViewHelper werden keine Optionen übergeben
array( 'ViewHelper',)
// Hier werden optionen an Error übergeben
array(  'Errors', array(
    'decorator' => array('xxx' => 'HtmlTag'),
    'options' => array('tag' => 'xxx')
  )),
// hier an das Label
  array('Label', array('tag' => 'xxx')),

// Wozu gehört dann das --> ??  
array(
    'decorator' => array('xxx' => 'HtmlTag'),
    'options' => array('tag' => 'xxx')
  )
));

Und vor allem: Wo kann ich sehen, welche Optionen man übergeben kann?
Blicke einfach nicht durch ?:roll:

DadyCool
 
Jeden der Decoratoren können auch Optionen im Form eines Array übergeben werden.
Was ich nun nicht verstehe:

Entspricht:
[...]

eigentlich dem?
[...]
vermute ich, kann ich dir aber nicht garantieren, es ist schon so lange her, dass ich das rausgesucht habe, ich würde auf jedenfall die 2. Variante bevorzugen, die kann man nämlich verstehen :biggrin:

Und vor allem: Wo kann ich sehen, welche Optionen man übergeben kann?
ka, aber es sind ja immer nur die gleichen, du kannst (soweit ich weiß) nur übergeben, welcher HTML-Tag genommen werden soll und du kannst noch Attribute bzw. CSS-Klassen definieren, das wars.

Blicke einfach nicht durch ?:roll:
wie gesagt, lass dein Vorhaben den Markup an deine Wünsche anzupassen, sondern style ihn nur über CSS. Der Markup ist schon gut, da er semantisch ist, ansonsten musst du eben weitergooglen und ggf. noch einige eigene Dekoratoren schreiben, viel zu viel Aufwand. Das tolle an Zend_Form ist ja, dass du es einfach verwenden kannst und dir um die Erzeugung des HTML keine Gedanken mehr machen musst, oder willst du für jedes weitere Projekt dich jeweils erstmal einen Tag hinsetzen und den Output von Zend_Form jeweils an deine ggf. immer neue Struktur für jedes Projektes anpassen?

Du kannst natürlich alternativ dein Formular auch manuell im View rendern (oder mit einem ViewHelper), wenn du unbedingt Wert drauflegst:
PHP:
<form action="<?php echo $this->form->getAction() ?>" method="<?php echo $this->form->getMethod() ?>" enctype="<?php echo $this->form->getEnctype() ?>">
  <?php foreach($form->getElements() as $element): ?>
    ...
  <?php endforeach ?>
</form>



Das Dekoratoren-Konzept von Zend_Form ist schon verdammt schwer, mir persönlich zu komplex, ich will programmieren und nicht erst stundenlang den Markup an jede Kleinigkeit anpassen. Vor allem weil der Markup ausreichend ist und mit den richtigen CSS-Selektoren sich sowieso auch alles nach Wunsch stylen lässt.
 
DANKE :)

wie gesagt, lass dein Vorhaben den Markup an deine Wünsche anzupassen, sondern style ihn nur über CSS. Der Markup ist schon gut, da er semantisch ist, ansonsten musst du eben weitergooglen und ggf. noch einige eigene Dekoratoren schreiben, viel zu viel Aufwand.

so werde ich das auch machen, wollte das nur für mein eigenes Verständnis einfach ausprobieren. Werde es aber jetzt erst mal lassen :)

Mfg
DadyCool
 
Es gibt wichtigere Dinge, die man voll verstehen sollte ;)
Zend_Controller ist z.B. solch eine Komponente, es ist eine der zentralsten Komponente und bei der sollte man sich dann auch supi auskennen, also Routing, Plugins, eigene Routen, ActionHelper usw. ;)