Zend_Form + Autocomplete

Da ich im Netz kein zufriedenstellendes Beispiel für Zend_Form in Verbindung mit Autocomplete finden konnte, möchte ich hier meinen Lösungsansatz zeigen. Vorraussetzungen sind hierfür ein Zend_Form, sowie aktiviertes jQuery + jQueryUI.

Im Formular passiert erstmal nix Besonderes. Es wird ein normales Zend_Form_Element_Text angelegt.

$autoCompleteElement = new Zend_Form_Element_Text('autoCompleteElement');

Der Controller bekommt eine zusätzliche autocompleteAction spendiert, welche wir dann später über jQuery ansprechen wollen, um die Werte zur aktuellen Eingabe zu erhalten. Wichtig ist hier, die Werte JSON-kodiert zu übergeben, um sie später im Javascript-File sauber auslesen zu können. Bei meinem $returnArray soll der Value später ins Formularfeld eingetragen werden, wohingegen das Label als Anzeige für die Auswahl beim Autocomplete gedacht ist.

public function autocompleteAction()
{
    $post = $this->_request->getPost();
    $searchString = $post['searchString'];
    
    // $returnArray zur Demonstration meiner übergebenen Daten
    $returnArray[$row['value']] = $row['label']; 
    $valuesJson = Zend_Json::encode($returnArray);
    echo $valuesJson;
    $this->view->layout()->disableLayout();
    $this->_helper->viewRenderer->setNoRender(true);
}

Das Javascript kümmert sich schlussendlich um das Absenden des Requests und das Mappen der empfangenen Daten.

$(document).ready(function() {
    $("input#autoCompleteElement").autocomplete({
        source : function( request, response) {
            url = "/meinModul/meinController/autocompleteAction";
            data = { 'searchString' : request.term };
            $.post(url, data, function(JSON){
                response($.map(JSON, function (item, value) {
                    return {
                        label: item,
                        value: value,
                        source: item};
                    }));
            }, 'json');
        },
        minLength: 1,
        autoFocus: true
    });
});

Zum Schluss natürlich nicht vergessen das Javascript in euer View-Script mit einzubinden.

Zend_Form mit mehreren Submit-Buttons

Benötigt man für ein Zend Formular mehrere Ausgänge, so bieten sich folgende Lösungen an:

  • Buttons, die per Javascript Aktionen auslösen
  • mehrere Submitbuttons

Variante 2 lässt sich recht einfach umsetzen. Zunächst ein Blick in den interessanten Teil des Formulars:

$delete = new Zend_Form_Element_Submit('delete');
$delete->setLabel('Löschen');

$duplicate = new Zend_Form_Element_Submit('duplicate');
$duplicate->setLabel('Duplizieren');

$submit = new Zend_Form_Element_Submit('submit');
$submit->setLabel('Absenden')

$this->addElements(array($delete, $duplicate, $submit));

Wir haben also drei verschiedene Submitbuttons angelegt und diese dann dem Formular zugewiesen. Als nächstes schauen wir uns die Formularverarbeitung bspw. im Controller an:

$form = new MyNewForm();
if ($this->getRequest()->isPost()) {
    $formData = $this->getRequest()->getPost();

    if ($form->submit->isChecked() 
        && $form->isValid($formData)) {
        // Form valide und Submitbutton wurde gedrückt
    }

    if ($form->delete->isChecked() 
        && $form->isValid($formData)) {
        // Form valide und Delete-Button wurde gedrückt
    }

    if ($form->duplicate->isChecked() 
        && $form->isValid($formData)) {
        // Form valide und Duplicate-Button wurde gedrückt
    }
}

Wir prüfen also zunächst, ob das Formular abgeschickt wurde, danach ob das Formular valide ist und der jeweilige Button gedrückt wurde. Über die Methode isChecked() des jeweiligen Formularelements bekommen wir jetzt recht simpel heraus, ob der Button gedrückt wurde.

[via]

XML definierte Zend_Forms – Validierung auf HTML Tags

Problem:
Eine über eine xml-Datei konfiguierte Zend_Form sollte validiert werden. Es sollte u.a. überprüft werden, ob HTML-Tags eingegeben wurden. Falls dies der Fall war, sollte das Formular nicht abgeschickt werden. Dazu wurde folgende Konfiguration (Auszug) verwendet:

<text type="textarea">
	<options required="1">
		<validators>
			<regex validator="Regex">
				<options>
					<pattern>(/[^<].*[>]/)</pattern>
				</options>
			</regex>
		</validators>
	</options>
</text>

Das Pattern ist in diesem Fall noch inkorrekt, da innerhalb von XML keine Zeichen wie „<" und "&" erlaubt sind. Der nächste Versuch war, die Zeichen mittels SQL Entities darzustellen.
Das Pattern sah dann wie folgt aus:

<pattern>(/[^&lt;].*[&gt;]/)</pattern>

Aber selbst dieser Ansatz brachte keine Lösung. Ein nächster Versuch war das einbetten des Codes in einen CDATA-Block.

<pattern><![CDATA["(/[^<].*[>]/)"]]></pattern>

Doch selbst dieser Ansatz lieferte weiterhin keine Lösung. Das Formular wurde nicht korrekt validiert.

Ein anderer Lösungsansatz brachte letztendlich den Erfolg: Das Schreiben einer eigenen Validatorklasse. In der XML-Konfiguration des Formulars muss nun nur noch folgender Aufruf stehen:

<text type="textarea">
	<options required="1">
		<validators>
			<regex validator="HtmlCheck" />
		</validators>
	</options>
</text>

Es wird nun der Validator HtmlCheck aufgerufen. Diesen müssen wir nun noch definieren. Wir legen dazu eine passende Validatorklasse an:

class Validate_HtmlCheck extends Zend_Validate_Abstract
{
	// [...]
	public function isValid($value)
	{
		//Prüfen, ob HTML Tags gesetzt wurden
		if($value!=strip_tags($value))
		{
			return false;
		}

		//Ansonsten true
		return true;
	}
}

Eventuell müsst ihr den Klassennamen entsprechend eurer eigenen Projektstruktur anpassen. Damit funktionierte das Validieren des Formulars auf HTML-Tags, wenn ihr euer Formular über XML definiert habt.

Vielleicht habt ihr ja noch eine elegantere Lösung?

Zend_Form über XML validieren

Ich habe auf slideshare.net ein gutes Tutorial zu Zend_Form in Verbindung mit XML gefunden.

Link:Zend Form Tutorial

Ein weiteres Tutorial, welches sich mit Zend_Form und XML beschäftigt, findet man auf der Seite von Pieter.

Passend dazu gibts auf der Zend Framework Seite eine Dokumentation zu den Validators.