Dzisiaj będzie coś dla wielbicieli Zend Frameworka. A dokładniej coś, z czym mamy do czynienia przetwarzając jakikolwiek formularz, czyli walidatory. Walidacja, a więc sprawdzanie czy wprowadzone przez użytkownika dane odpowiadają pewnemu schematowi jest obok filtracji, czyli wyrzucaniu zbędnych/niebezpiecznych rzeczy z danych chyba najważniejszą sprawą przy tworzeniu witryn WWW.
Zend Framework dysponuje zestawem kilkudziesięciu walidatorów, które można łączyć w łańcuchy przy walidowaniu poszczególnych pól formularza, np. pytając o wiek użytkownika pole musi zawierać wyłącznie liczby, czyli aż prosi się o Zend_Validate_Digits
, a następnie należy sprawdzić czy podana liczba znajduje się w jakimś ludzkim przedziale, tzn. powiedzmy pomiędzy 1 a 100, co załatwi za nas Zend_Validate_Between
.
Co w przypadku jeżeli musimy dopasowywać coś, czego nie przewidzieli twórcy ZF? Możemy napisać własny walidator.
Każdy walidator musi implementować interfejs Zend_Validate_Interface
, czyli dwie publiczne metody:
isValid($value)
— zwracająca buliona prawda/fałsz
getMessages()
— zwracająca tablicę komunikatów co jest nie tak z wartością testowaną w isValid(). Komunikaty zwracane są w postaci kod_błędu => komunikat_w_ludzkiej_formie
W celu uniknięcia babrania się obsługą błędów i komunikatów twórcy ZF stworzyli abstrakcyjną klasę Zend_Validate_Abstract
, która zrobi za nas większość brudnej roboty. Pozostanie nam tylko napisanie właściwej logiki co ma być sprawdzane i ewentualnie jaki błąd zgłaszany.
Na potrzeby swojej aplikacji napisałem własny w miarę uniwersalny walidator, który sprawdzi czy klucz podstawowy danej tablicy istnieje. Może mieć zastosowanie jeżeli ktoś sprawdza czy np. identyfikator wybranej przez użytkownika kategorii istnieje w bazie.
Poniżej przedstawiem kod z objaśnieniami po co coś jest. Po przeczytaniu stwierdzicie, że pisanie walidatorów to fajna zabawa
<?php
// rozszerzamy klasę abstrakcyjną dla walidatorów
class Spiechu_Validators_IsIdExists extends Zend_Validate_Abstract {
// definiujemy kody błędów i jakieś wartości dla nich
const IDNOTEXISTS = 'idnotexists';
const EMPTYSTRING = 'emptystring';
const NULLVALUE = 'nullvalue';
// definiujemy tablicę komunikatów błędów dla poszczególnych kodów
// zwracam uwagę na '%value', które może być w locie zamienione na sprawdzaną wartość
protected $_messageTemplates = array(
self::IDNOTEXISTS => "id '%value%' not exists",
self::EMPTYSTRING => 'given value is empty',
self::NULLVALUE => 'given value is null'
);
// zmienna typu Zend_Db_Table_Abstract, której klucz będziemy testować
protected $_table;
public function __construct(Zend_Db_Table_Abstract $table) {
$this->_table = $table;
}
public function isValid($value) {
// sprawdzamy czy zmienna nie jest nulem, a jeżeli tak to ustawiamy błąd
if ($value === null) {
$this->_error(self::NULLVALUE);
return false;
}
// to samo dla pustego stringa
if ($value === '') {
$this->_error(self::EMPTYSTRING);
return false;
}
$value = (int) $value;
// ustawiamy wartość dla ewentualnego komunikatu %value%
$this->_setValue($value);
// metoda find szuka po kluczu podstawowym i zwraca rowset wyników
$foundRows = $this->_table->find($value);
// jeżeli nic nie znaleziono tzn. że sprawdzany klucz nie istenieje w tabeli bazy
if (count($foundRows) == 0) {
$this->_error(self::IDNOTEXISTS);
return false;
}
else {
return true;
}
}
}
Wszystko działa na tyle automagicznie, że tworząc jakiś element formularza wystarczy dodać stworzony walidator np. tak:
$formElement = new Zend_Form_Element_Select('pole_formularza');
$formElement->setRequired(true)
->setLabel('Jakaś etykieta')
->setMultiOptions($dane_do_wyboru)
->addValidator(new Spiechu_Validators_IsIdExists(new Sprawdzana_Tabela()));