ZF: Długości pól formularza na podstawie bazy
18 Styczeń 2011 Dodaj komentarz
Kiedy tworzymy formularz w Zend Frameworku przesyłamy potem dane z niego do bazy. Czasem się okazuje, że długość wprowadzanych danych przekracza długość pola tabeli i przez to pojawia się błąd w stylu “String data, right truncated: 7 ERROR value too long for type character varying(40)” (PostgreSQL). Żeby temu zapobiec można ustawić dodatkowe walidatory dla pól formularza, które będą bazowały na informacjach z metadanych tabeli. Można to osiągnąć m.in. tak:
public function ustawWalidatory($aMetadane, $bInfoLabel = true)
{
$elementy = $this->getElements();
foreach($elementy as $sNazwa => $element) {
$sNazwa = narzedziownia::fromCamelCase($sNazwa);
if(!empty($aMetadane[$sNazwa]['LENGTH'])
&& !$element instanceof Zend_Form_Element_Hidden
&& !$element instanceof Zend_Form_Element_Checkbox
&& $aMetadane[$sNazwa]['DATA_TYPE'] != 'date') {
$nLength = $aMetadane[$sNazwa]['LENGTH'];
$element->addValidator('StringLength', false, array(
'min' => 1,
'max' => $nLength,
'messages' => array(
'stringLengthInvalid' => 'Nie przesłano stringa, tylko coś innego',
'stringLengthTooShort' => 'Za krótki ciąg znaków, wymagane co najmniej %min%',
'stringLengthTooLong' => 'Za długi ciąg znaków, wymagane najwyżej %max%'
)
));
// doklej informację do 'labela'
if($bInfoLabel) {
$element->setLabel($element->getLabel() . ' [' . $nLength . ']');
}
}
}
}
Po kolei. Funkcję dodajemy do formularza
// application/forms/NaszForm.php
public NaszForm extends Zend_Form
{
public function init()
{
// tutaj inicjalizacja formularza
}
public function ustawWalidatory($aMetadata)
{
// tutaj treść funkcji jak wyżej
}
}
Żeby pobrać metadane wystarczy wywołać metodę info() dla naszego modelu rozszerzającego Zend_Db_Table_Abstract (patrz: Zend_Db_Table_Abstract->info()).
Przelatujemy po wszystkich elementach dodanych do formularza. Sprawdzamy, czy dane pole przypadkiem nie jest checkboxem lub polem ukrytym (hidden) i czy ma w ogóle ustawioną długość (np. pole typu varchar bez podanej długości lub typu text – nie ma). Jeśli tak – ustaw walidator długości znaków od 1 do długości pola tabeli. Jeśli pole nie jest wymagane, to można ustawić długość od zera (min => 0). Na koniec ustawienie komunikatów walidatora i doklejenie informacji o długości pola do elementu Label.
Dobra, jeszcze jak to wywołać. Tu jest minus, bo nie zrobimy tego przekazując parametr do metody Zend_Form::init() – bo nie przyjmuje ona parametrów. Można wywołać funkcję niezależnie, np:
$form = new NaszForm();
// $tabela jest typu rozszerzającego Zend_Db_Table_Abstract
$aMetadane = $tabela->info('metadata');
$form->ustawWalidatory($aMetadane);
lub wykorzystać fakt, że przy tworzeniu obiektu klasy Zend_Form (lub dziedziczącej) w konstruktorze wywoływana jest metoda setOptions(), która może wywołać dowolną zdefiniowaną przez nas metodę, która zaczyna się od set. Czyli coś w tym stylu:
// $tabela jest typu rozszerzającego Zend_Db_Table_Abstract
$aMetadane = $tabela->info('metadata');
$form = new NaszForm(array(
'walidatory' => array(
'metadane' => $aMetadane
)
));
Wówczas NaszForm musi posiadać metodę setWalidatory($aWalidatory), która ustawi walidatory. Mnie wygodnie było to zrobić tak:
public function setWalidatory(array $aWalidatory)
{
$aMetadane = $aWalidatory['metadane'];
$bInfoLabel = strlen($aWalidatory['infolabel']) > 0 ? $aWalidatory['infolabel'] : true;
$this->ustawWalidatory($aMetadane, $bInfoLabel);
}
Można też bezpośrednio zmienić nazwę metody ustawWalidatory() na setWalidatory() i odpowiednio ustawić parametry.
I powinno działać.