Das 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.