Zend Framework: Ein eigener Validator
PHP Juli 8th, 2008Das Zend Framework kommt mit vielen Fertigklassen – sozusagen „batteries included“. Jedoch für folgende Konstellation habe ich nichts gefunden: Ein Kontaktformular, das durch Zend Form und Zend Validate unterstützt wird, und bei dem entweder die E-Mail Adresse oder die Telefonnummer mindestens ausgefüllt sein muss. (Und natürlich valide sein muss)
Grund genug, sich mit dem Zend Framework etwas vertrauter zu machen, und einen eigenen Validator zu entwickeln, der genau diese Situation abdeckt.Um einen eigenen Zend Validator zu entwickeln, verwendet man am besten Zend_Validate_Abstract als Basisklasse. Auch sollte der Validator konfigurierbar sein. Sonderfall für diesen Zend Validator: Er benötigt den „Kontext“ – ein einzelnes Feld alleine ist nicht validierbar, denn es ist gut möglich, dass eine leere Eingabe dadurch valide wird, dass eines der anderen benötigten Felder ausgefüllt wird.
Hier also der Quellcode des Validators:
<?php
require_once ‚Zend/Validate/Abstract.php‘;
class AtLeastOneValidator extends Zend_Validate_Abstract
{
const REQUIRED_EMPTY = ‚requiredFieldsEmpty‘;
protected $_messageTemplates = array(
self::REQUIRED_EMPTY => ‚At least one of the fields must contain a value: %value%‘
);
private $requiredFields;
private $requiredFieldKeys;
function __construct()
{
$this->requiredFields = array();
$this->requiredFieldKeys = array();
}
public function addField(&$field)
{
array_push($this->requiredFieldKeys, $field->getName());
array_push($this->requiredFields, &$field);
}
public function isValid($value, $context = null)
{
$size = count($this->requiredFieldKeys);
//if no fields required, return success
if ($size <= 0)
{
return true;
}
if (is_array($context))
{
$empty = true;
foreach (array_keys($context) as $field)
{
if (in_array($field, $this->requiredFieldKeys) )
{
if (! empty($context[$field]))
{
$empty = false;
break;
}
}
}
if ($empty)
{
$value=““;
foreach ($this->requiredFields as $field)
{
$value .= $field->getLabel() . „, „;
}
$value=substr($value, 0, -2); //remove colon
$this->_error(self::REQUIRED_EMPTY, $value);
return false;
}
return true;
}
echo „no context in validator“;
exit; // throw exception
}
}
?>
Etwas verkompliziert wurde die Situation dadurch, dass das Zend Framework als Kontext keine Objekte übergibt, sondern ein assoziatives Array der Form Feldname->Feldwert. Aber ein bisschen „komisch“ darf PHP ja sein.
So wird der eigene Zend Validator dann verwendet:
$email = new Zend_Form_Element_Text(‚email‘);
$email->setLabel(‚Email-Addresse‘)
->addFilter(‚StringToLower‘)
->addValidator(‚EmailAddress‘);
$phone = new Zend_Form_Element_Text(‚phone‘);
$phone->setLabel(‚Telefonnummer‘)->addFilter(„Digits“);
$phone->setRequired(false);
$phone->setAllowEmpty(false);
$phone->setAutoInsertNotEmptyValidator(false);
$val = new AtLeastOneValidator();
$val->addField($email);
$val->addField($phone);
$phone->addValidator($val);
Dabei ist zu beachten, dass der Validator lediglich an ein Feld angebunden wird.
August 5th, 2009 at 12:32
Die Validierung von mehr als einem Feld auf einmal bedarf wohl immer eines eigenen Validators. Was man z.B. auch häufig haben wird, ist z.B. die doppelte Abfrage eines Passwortes oder der Emailadresse im Verlauf einer Benutzer-Registration. Dafür gibts mittlerweile den Validator Identical. Für eine anständige Doku muss man aber woanders gucken… Hier ist etwas, was ein bisschen eine Idee von der Funktionsweise vermittelt: Identical Validator and comparing form fields. Viel Erfolg 😉