1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
|
<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24249 -->
<!-- Reviewed: no -->
<sect1 id="zend.validate.writing_validators">
<title>Schreiben von Prüfern</title>
<para>
<classname>Zend_Validate</classname> bietet ein Set von standardmäßig benötigten Prüfern,
aber zwangsläufig, werden Entwickler wünschen, eigene Prüfer für die eigenen Bedürfnisse zu
schreiben. Die Aufgabe des Schreibens eigener Prüfer wird in diesem Kapitel beschrieben.
</para>
<para>
<classname>Zend_Validate_Interface</classname> definiert zwei Methoden,
<methodname>isValid()</methodname> und <methodname>getMessages()</methodname>, welche von
Benutzerklassen implementiert werden können um eigene Prüfobjekte zu erstellen. Ein Objekt
welches das <classname>Zend_Validate_Interface</classname> Interface implementiert kann
einer Prüfkette mit <methodname>Zend_Validate::addValidator()</methodname> hinzugefügt
werden. Solche Objekte können auch mit <link
linkend="zend.filter.input"><classname>Zend_Filter_Input</classname></link> verwendet
werden.
</para>
<para>
Wie man bereits aus der obigen Beschreibung von
<classname>Zend_Validate_Interface</classname> folgern kann, geben die vom Zend Framework
bereitgestellten Prüfklassen einen boolschen Wert zurück, ob die Prüfung des Wertes
erfolgreich war oder nicht. Sie geben auch darüber Informationen
<emphasis>warum</emphasis> ein Wert die Prüfung nicht bestanden hat. Die
Verfügbarkeit der Gründe für fehlgeschlagene Prüfungen kann für eine Anwendung aus vielen
Gründen nützlich sein, wie zum Beispiel das zur Verfügung stellen von Statistiken für
Useability Analysen.
</para>
<para>
Grundlegende Funktionalitäten für fehlgeschlagene Prüfmeldungen ist in
<classname>Zend_Validate_Abstract</classname> implementiert. Um diese Funktionalität
einzubinden wenn eine Prüfklasse erstellt wird, muß einfach
<classname>Zend_Validate_Abstract</classname> erweitert werden. In der existierenden Klasse
wird die Logik der <methodname>isValid()</methodname> Methode implementiert und die
Variablen für die Nachrichten und Nachrichten-Templates definiert werden die zu den Typen
von Prüffehlern passen die auftreten können. Wenn ein Wert die Prüfung nicht besteht, sollte
<methodname>isValid()</methodname> <constant>FALSE</constant> zurückgeben. Wenn der Wert die
Prüfung besteht, sollte <methodname>isValid()</methodname> <constant>TRUE</constant>
zurückgeben.
</para>
<para>
Normalerweise sollte die <methodname>isValid()</methodname> Methode keine Ausnahmen werfen,
ausser wenn es unmöglich ist festzustellen ob ein Eingabewert gültig ist oder nicht. Einige
Beispiele für gute Fälle in denen keine Ausnahme geworfen werden sollte sind, wenn eine
Datei nicht geöffnet werden konnte, ein <acronym>LDAP</acronym> Server nicht erreicht wurde,
oder eine Datenbank Verbindung unerreichbar ist, und wo solche Dinge für Prüfprozesse
benötigt werden um zu erkennen ob die Prüfung gültig oder ungültig ist.
</para>
<example id="zend.validate.writing_validators.example.simple">
<title>Erstellen einer einfachen Prüfklasse</title>
<para>
Das folgende Beispiel demonstriert wie ein sehr einfacher eigener Prüfer geschrieben
werden könnte. In diesem Fall sind die Prüfregeln sehr einfach und der Eingabewert muß
ein Gleitkommawert sein.
</para>
<programlisting language="php"><![CDATA[
class MyValid_Float extends Zend_Validate_Abstract
{
const FLOAT = 'float';
protected $_messageTemplates = array(
self::FLOAT => "'%value%' ist kein Gleitkommawert"
);
public function isValid($value)
{
$this->_setValue($value);
if (!is_float($value)) {
$this->_error();
return false;
}
return true;
}
}
]]></programlisting>
<para>
Die Klasse definiert ein Template für Ihre einzige Nachricht bei Prüfungsfehlern, welche
den eingebauten magischen Parameter <emphasis>%value%</emphasis> inkludiert. Der Aufruf
von <methodname>_setValue()</methodname> präpariert das Objekt den getesteten Wert
automatisch in die Fehlernachricht einzufügen, wenn die Prüfung des Wertes fehlschlägt.
Der Aufruf von <methodname>_error()</methodname> spürt den Grund für die fehlgeschlagene
Prüfung auf. Da diese Klasse nur eine Fehlernachricht definiert, ist es nicht notwendig
<methodname>_error()</methodname> den Namen des Templates der Fehlernachricht zu geben.
</para>
</example>
<example id="zend.validate.writing_validators.example.conditions.dependent">
<title>Schreiben einer Prüfklasse die abhängige Konditionen besitzt</title>
<para>
Das folgende Beispiel demonstriert ein komplexeres Set von Prüfregeln, wobei es
notwendig ist das der Eingabewert nummerisch und innerhalb eines Bereiches von Mindest-
und Maximalgrenzwerten ist. Bei einem Eingabewert würde die Prüfung wegen exakt einer
der folgenden Gründe fehlschlagen:
</para>
<itemizedlist>
<listitem>
<para>Der Eingabewert ist nicht nummerisch.</para>
</listitem>
<listitem>
<para>Der Eingabewert ist kleiner als der minimal erlaubte Wert.</para>
</listitem>
<listitem>
<para>Der Eingabewert ist größer als der maximal erlaubte Wert.</para>
</listitem>
</itemizedlist>
<para>
Diese Gründe für fehlgeschlagene Prüfungen werden in Definitionen der Klasse übersetzt:
</para>
<programlisting language="php"><![CDATA[
class MyValid_NumericBetween extends Zend_Validate_Abstract
{
const MSG_NUMERIC = 'msgNumeric';
const MSG_MINIMUM = 'msgMinimum';
const MSG_MAXIMUM = 'msgMaximum';
public $minimum = 0;
public $maximum = 100;
protected $_messageVariables = array(
'min' => 'minimum',
'max' => 'maximum'
);
protected $_messageTemplates = array(
self::MSG_NUMERIC => "'%value%' ist nicht nummerisch",
self::MSG_MINIMUM => "'%value%' muß mindestens '%min%' sein",
self::MSG_MAXIMUM => "'%value%' darf nicht mehr als '%max%' sein"
);
public function isValid($value)
{
$this->_setValue($value);
if (!is_numeric($value)) {
$this->_error(self::MSG_NUMERIC);
return false;
}
if ($value < $this->minimum) {
$this->_error(self::MSG_MINIMUM);
return false;
}
if ($value > $this->maximum) {
$this->_error(self::MSG_MAXIMUM);
return false;
}
return true;
}
}
]]></programlisting>
<para>
Die öffentlichen Eigenschaften <varname>$minimum</varname> und
<varname>$maximum</varname> wurden eingeführt um die Mindest- und Maximalgrenzen
anzubieten, beziehungsweise, für einen Wert um die Prüfung erfolgreich zu bestehen. Die
Klasse definiert auch zwei Nachrichtenvariablen die zu den öffentlichen Eigenschaften
korrespondieren und es erlauben <property>min</property> und <property>max</property> in
den Nachrichten Templates als magische Parameter zu verwenden, genauso wie
<property>value</property>.
</para>
<para>
Zu beachten ist, das wenn eine der Prüfungen in <methodname>isValid()</methodname>
fehlschlägt, eine entsprechende Fehlernachricht vorbereitet wird, und die Methode sofort
<constant>FALSE</constant> zurückgibt. Diese Prüfregeln sind deswegen sequentiell
abhängig. Das bedeuted, wenn einer der Tests fehlschlägt, gibt es keinen Grund eine
weitere nachfolgende Prüfregel zu testen. Das muß aber trotzdem nicht der Fall sein. Das
folgende Beispiel zeigt wie man eine Klasse schreiben kann die unabhängige Prüfregeln
besitzt, wo die Prüfobjekte mehrfache Gründe zurückgeben könnten, warum ein spezieller
Prüfversuch fehlgeschlagen ist.
</para>
</example>
<example id="zend.validate.writing_validators.example.conditions.independent">
<title>Prüfen mit unabhängigen Konditionen, mehrfache Gründe für Fehler</title>
<para>
Angenommen es wird eine Prüfklasse geschrieben für das Erzwingen von Passwortstärke -
wenn ein Benutzer ein Passwort auswählen muß das diversen Kriterien entspricht um zu
Helfen das die Benutzerzugänge sicher sind. Angenommen die Passwort Sicherheitskriterien
erzwingen das folgende Passwort:
</para>
<itemizedlist>
<listitem><para>mindestens 8 Zeichen Länge,</para></listitem>
<listitem><para>enthält mindestens ein großgeschriebenes Zeichen,</para></listitem>
<listitem><para>enthält mindestens ein kleingeschriebenes Zeichen,</para></listitem>
<listitem><para>und enthält mindestens eine Ziffer.</para></listitem>
</itemizedlist>
<para>
Die folgende Klasse impementiert diese Prüfkriterien:
</para>
<programlisting language="php"><![CDATA[
class MyValid_PasswordStrength extends Zend_Validate_Abstract
{
const LENGTH = 'length';
const UPPER = 'upper';
const LOWER = 'lower';
const DIGIT = 'digit';
protected $_messageTemplates = array(
self::LENGTH => "'%value%' muß mindestens 8 Zeichen lang sein",
self::UPPER => "'%value%' muß mindestens ein großgeschriebenes "
. "Zeichen enthalten",
self::LOWER => "'%value%' muß mindestens ein kleingeschriebenes "
. "Zeichen enthalten",
self::DIGIT => "'%value%' muß mindestens eine Ziffer enthalten"
);
public function isValid($value)
{
$this->_setValue($value);
$isValid = true;
if (strlen($value) < 8) {
$this->_error(self::LENGTH);
$isValid = false;
}
if (!preg_match('/[A-Z]/', $value)) {
$this->_error(self::UPPER);
$isValid = false;
}
if (!preg_match('/[a-z]/', $value)) {
$this->_error(self::LOWER);
$isValid = false;
}
if (!preg_match('/\d/', $value)) {
$this->_error(self::DIGIT);
$isValid = false;
}
return $isValid;
}
}
]]></programlisting>
<para>
Zu beachten ist das diese vier Testkriterien in <methodname>isValid()</methodname> nicht
sofort <constant>FALSE</constant> zurückgeben. Das erlaubt der Prüfklasse
<emphasis>alle</emphasis> Gründe anzubieten bei denen das Eingabepasswort
den Prüfvoraussetzungen nicht entsprochen hat. Wenn, zum Beispiel, ein Benutzer den
String "#$%" als Passwort angegeben hat, würde
<methodname>isValid()</methodname> alle vier Prüfungfehlermeldungen zurückgeben bei
einen nachfolgenden Aufruf von <methodname>getMessages()</methodname>.
</para>
</example>
</sect1>
|