Empfehlungen: Erweiterte Suche

Angepasste Fehlermeldungen

Anleitungen und Quellcode-Auszüge die den Start vereinfachen sollen.

Angepasste Fehlermeldungen

Beitragvon Mathias » Mi 4. Mär 2009, 18:52

Tritt beim Absenden eines Formulars ein Fehler durch falsche Eingabe auf, sollte man dem User mitteilen, was er falsch gemacht hat. Über die Validierung im Model lassen sich Meldungen für bestimmte Fehler definieren.
Sollte ein Fehler auftreten, so packt Cake die Fehlermeldung direkt unter das Eingabefeld, in dem der Fehler ist und weist dem div eine Fehlerklasse zu.
Fehlermeldungen lassen sich im Model definieren
Code: Alles auswählen
    var $validate = array(
        'title' => array(
            'rule' => array('minLength', '5')),
            'message' => 'Titel muss länger als 5 Zeichen sein.'
        )
    );

Ist der Titel kürzer als 5 Zeichen, erscheint die Fehlermeldung direkter unter dem input des Formulars.

Nun kann es sein, dass man die Fehlermeldungen gar nicht unter den jeweiligen inputs haben möchte, sondern in gebündelter Form über den Eingabefeldern. Der Formhelper bietet die Möglichkeit, die Fehlermeldungen in der View separat zu behandeln.
Code: Alles auswählen
echo $form->error('title');

Nun wird die Fehlermeldung an Ort und Stelle ausgegeben.

Es gibt aber auch einen anderen Weg, die Fehlerbeschreibung auf dem Schirm zu bekommen. Einige Kommentare in der weiten Welt des Internets besagen, dass der Cake’sche Weg nicht über die 'message'-Definition geht, sondern alle Fehlermeldungen in der View stehen. Also wird lediglich der Fehler aus dem Model an die View gegeben. Das mag im Model alles übersichtlicher sein, so ist es aber nicht DRY, denn in jeder View müssen nun die Fehlermeldungen immer wieder geschrieben werden. Beispiel wäre 1x add und 1x edit. Beide benutzen die gleiche Validierung.

Ein weiterer Punkt ist die Internationalisierung. Hier gibt es zwei Ansätze: Die Übersetzung im Model oder die Übersetzung in der View. Laut Recherche im Internet hat die Übersetzung von Strings nicht im Model stattzufinden, sondern in der View. Des Weiteren lassen sich Strings auch nicht einfach so im Model á la __() übersetzen. Hierzu müsste ein parent constructor benutzt werden, der $valiadte umschließt. Das heißt also, wir übergeben nur den Fehler (id oder als eindeutiger string) an die View und der Formhelper wurstest uns nun die Meldung zusammen. Unabhängig davon, ob es nun richtig oder falsch ist, die Strings in der View anstatt im Model zu übersetzen, bevorzuge ich die Variante in der View. Fein säuberlich aufgelistet und man kann unter Umständen für die gleiche Validierung unterschiedliche Meldungen ausgeben (add oder edit).
Wie oben schon angesprochen, kann man den Validierungsfehler an die View als String oder als ID übergeben. Im folgenden Beispiel werden die Fehler anhand der Fehler-ID erkannt. Im Model sieht das Ganze so aus:
Code: Alles auswählen
    var $validate = array(
        'first_name' => array(
            array('rule' => array('custom', '/^\p{Lu}(\p{Ll})+([-| ]\p{Lu}\p{Ll})*$/u')),
            VALID_NOT_EMPTY
        ),
        'last_name' => array(
            array('rule' => array('custom', '/^(\p{Lu}(\p{Ll})+([-| ]\p{Lu}\p{Ll})*)|([a-z]+ (\p{Lu}(\p{Ll})+))$/u')),
            VALID_NOT_EMPTY
        ),
        'username' => array(
            array('rule' => 'alphaNumeric'),
            VALID_NOT_EMPTY,
            array('rule' => array('isUnique'))
        ),
        'email' => array(
            array('rule' => 'email'),
            VALID_NOT_EMPTY
        ),
        'new_password' => array(
            array('rule' => array('identicalFieldValues', 'password2')),
            array('rule' => array('minLength', '5'))
        )
    );

In der View dann folgendes:
Code: Alles auswählen
                echo $form->error('first_name', array(
                                                0 => __('First name can only contain letters, - and whitespace', true),
                                                1 => __('First name must not be empty', true)
                                                )
                );
                echo $form->error('last_name', array(
                                                0 => __('Last name can only contain letters, - and whitespace', true),
                                                1 => __('Last name must not be empty', true)
                                                )
                );
                echo $form->error('username', array(
                                                0 => __('Username must contain letters or digits', true),
                                                1 => __('Username must not be empty', true),
                                                3 => __('Username already in use', true)
                                                )
                );
                echo $form->error('email', array(
                                                0 => __('E-Mail must be a valid address', true),
                                                1 => __('E-Mail must not be empty', true)
                                                )
                );
                echo $form->error('new_password', array(
                                                0 => __('Passwords do not match', true),
                                                1 => __('Password must have more than 5 characters', true)
                                                )
                );

Vergleich man nun die Reihenfolge der Validierungsregeln mit den Fehlermeldungen, wird man schnell rausfinden, dass es sich um die gleiche Reihenfolge handelt. Will man nun die Fehler anhand von eindeutigen Strings rausfinden, fügt man im Model einfach den Fehlernamen hinzu:
Code: Alles auswählen
[..]
        'first_name' => array(
            'onlyLetters' => array('rule' => array('custom', '/^\p{Lu}(\p{Ll})+([-| ]\p{Lu}\p{Ll})*$/u')),
            'notEmpty' => VALID_NOT_EMPTY
        ),
[..]

In der View dann folgendes:
Code: Alles auswählen
                echo $form->error('first_name', array(
                                                'onlyLetters' => __('First name can only contain letters, - and whitespace', true),
                                                'notEmpty' => __('First name must not be empty', true)
                                                )
                );


Das mag vielleicht alles ein wenig durcheinander klingen und es gibt bestimmt noch andere Möglichkeiten, Fehlermeldungen in Cake zu behandeln, aber ich finde diesen Weg nachvollziehbar, einfach und übersichtlich. Falls sich noch Fragen oder Verbesserungsvorschläge dazu ergeben, immer her damit.

Anmerkung: Die oben aufgeführten Beispiele sind nur Codeschnipsel und werden zum Teil nicht nach Copy&Paste funktionieren. Also Augen auf beim Kopieren ;)
cheers
Benutzeravatar
Mathias
 
Beiträge: 225
Registriert: Mi 4. Jun 2008, 22:30
Wohnort: Berlin
CakePHP-Version: 1.3.x
OS: OS X 10.6.x

Re: Angepasste Fehlermeldungen

Beitragvon euromark » Fr 6. Mär 2009, 08:28

ich persönlich fand immer den "model" weg am einfachsten und bequemsten - und quasi am DRYsten
so muss nur zentral an einer stelle eine änderung gemacht werden, statt sie dann in bis zu 5 views/elements etc dann noch nachzuziehen

aber natürlich hast du völlig recht. schon bei der i18n des Ganzen stoßen wir an unsere Grenzen
man kann $this->invalidate() etc überschreiben und automatisch übersetzen lassen,
deine "inviduellen Fehlermeldungen" pro view kriegt man so natürlich trotzdem nicht hin

und ein weiterer Punkt, der gegen den bequemen model-weg spricht, ist evtl eine nachträgliche Änderung der Fehlermeldung.
Stellen wir uns mal vor, wir möchten der Meldung noch die Anzahl der eingegebenen Zeichen mitgeben:
"Erlaubt sind 100 Zeichen - Sie haben 30 zu viel eingegeben" oder sowas

Wobei ich es noch nicht geschafft habe, dies umzusetzen.
Weiß jemand wie das ginge? habe versucht hier ne eigene validierungsregel aufzusetzen, die das "error" field überschreibt, allerdings geht das nicht.
evtl mit an den view übergeben? und dann mit %s und sprintf()?

mark
euromark
 
Beiträge: 618
Registriert: Fr 27. Jun 2008, 22:17
Wohnort: München
CakePHP-Version: 2.1
OS: Windows

Re: Angepasste Fehlermeldungen

Beitragvon Mathias » Fr 13. Mär 2009, 11:27

Man koennte vielleicht $this->data auslesen und dann halt die Laenge des Strings ermitteln und mit der Variable von der Validation vergleichen und die Differenz halt ausgeben.
Aber irgendwo speichert cake bestimmt die Differenz, man muss es bloß finden ;)
cheers
Benutzeravatar
Mathias
 
Beiträge: 225
Registriert: Mi 4. Jun 2008, 22:30
Wohnort: Berlin
CakePHP-Version: 1.3.x
OS: OS X 10.6.x


Zurück zu Tutorials und Snippets

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste