2011-01-28 8 views
6

Mam element. Chcę dodać do niego niestandardowy weryfikator i filtr niestandardowy. Walidator upewnia się, że dane wejściowe są jedną z kilku dozwolonych wartości, a następnie filtr dodaje do wejścia wartości niestandardowe. Oznacza to, że najpierw muszę sprawdzić oryginalne dane wejściowe przed uruchomieniem filtra. Robię to w tej kolejności:Sposób wykonania tego filtru po tym Validatorze

$element = new Zend_Form_Element_Text('element'); 
$element->addValidator('PermittedValue', false); 
$element->addFilter('TotalHyphen', false); 
$this->addElement($element); 

, ale to zamówienie nie jest przestrzegane. Filtr uruchamia się jako pierwszy i zmienia dane, a następnie walidator działa na filtrowanych danych, co oznacza, że ​​zawsze kończy się niepowodzeniem, nawet w przypadku prawidłowego wprowadzania danych. Wydaje się, ze documentation że jest to celowe

Uwaga: Walidacja Działa filtrowanych wartości Zend_Form_Element :: isValid() Filtry wartości poprzez dołączonego łańcucha filtra wcześniejszej walidacji. Zobacz sekcję Filtry, aby uzyskać więcej informacji na temat .

Jak mogę określić kolejność uruchamiania walidatorów i filtrów?

Odpowiedz

7

Wygląda na to, że stworzenie niestandardowego elementu obsługującego filtrowanie po walidacji byłoby rozwiązaniem.Jak o tym:

/** 
* An element that supports post-validation filtering 
*/ 
class My_Form_Element_PostValidateFilterable extends Zend_Form_Element_Text 
{ 
    protected $_postValidateFilters = array(); 

    public function setPostValidateFilters(array $filters) 
    { 
     $this->_postValidateFilters = $filters; 
     return $this; 
    } 

    public function getPostValidateFilters() 
    { 
     return $this->_postValidateFilters; 
    } 

    public function isValid($value, $context = null) 
    { 
     $isValid = parent::isValid($value, $context); 
     if ($isValid){ 
      foreach ($this->getPostValidateFilters() as $filter){ 
       $value = $filter->filter($value); 
      } 
      $this->setValue($value); 
     } 
     return $isValid; 
    } 
} 

Wykorzystanie byłoby coś takiego:

$elt = $form->addElement('PostValidateFilterable', 'myElement', array(
    'label' => 'MyLabel', 
    'filters' => array(
     'StringTrim', 
     // etc 
    ), 
    'validators' => array(
     'NotEmpty', 
     // etc 
    ), 
    // here comes the good stuff 
    'postValidateFilters' => array(
     new My_Filter_RunAfterValidateOne(), 
     new My_Filter_RunAfterValidateTwo(), 
    ), 
)); 

To utrzymuje walidacji i filtrowanie w formie - prowadzenie kontroler cienkie.

Nie przetestowany, tylko przebicie w ciemności. I na pewno można tu spasować/zmodyfikować API, aby dodawać/usuwać filtry według klucza, itp.

Co myślisz?

+0

+1. Wygląda bardzo ładnie. Nie wiedziałem również, że metoda setPostValidateFilters() zostanie wywołana automatycznie (tak?) Dla klucza "postValidateFilters". – Marcin

+0

@Marcin: Myślę, że tak działają opcje. Jeśli istnieje metoda, która "pasuje" do nazwy opcji, wówczas ta metoda zostanie wywołana podczas 'setOptions()'. –

+0

+1 bardzo ładna realizacja – tawfekov

4

Może nie dodawaj filtra w ogóle. Zweryfikować treść jako pierwsza w sterowniku, a następnie użyć filtru oddzielnie:

$request = $this->getRequest(); 
if ($request->isPost() && $form->isValid($request->getParams())) { 
    $filter = new Filter_Whatever(); 
    $val = $filter->filter($request->getParam('element')); 
    ... //call your model or whatever 
} 

Nigdy nie robiłem tego, ale przypuszczam, że to może (lub coś podobnego) działa.

+0

+1 To możliwe rozwiązanie, ale nie jestem pewien, czy mi się podoba. Zrobię to, jeśli wszystko inne zawiedzie, ale wolałbym utrzymać cienki kontroler i zachować logikę filtrowania z elementem formularza, do którego należy. – jblue

+0

Oczywiście, wolałbym zachować go również w kodzie formularza, ale nie mogę wymyślić innego sposobu wpływania na kolejność, w której sprawdzane są walidatory i filtry. Czasami dodam do kontrolera również takie rzeczy, które powinny idealnie znajdować się w formularzu, na przykład, gdy zestaw pól jest wymagany wtedy i tylko wtedy, gdy coś innego jest zaznaczone/wypełnione. Nie można wiarygodnie sprawdzić tego po stronie klienta lub przed wypełnieniem formularza przez użytkownika, więc czasami potrzeba dodatkowej magii formy w kontrolerze, na przykład: – mingos

1

Dobra uwaga! ,

filtry AFAIK powinien lub musi uruchomić przed walidacji wejścia: z ZF docs

Jest to często przydatne i/lub konieczne wykonać pewną normalizację na wejściu przed walidacji. Na przykład użytkownik może chcieć usunąć cały kod HTML, ale przeprowadzi walidacje na tym, co pozostaje , aby upewnić się, że przesłanie jest prawidłowe. Lub możesz przyciąć puste miejsce otaczające dane wejściowe, aby walidator StringLength używał prawidłowej długości wejścia bez zliczania znaków początkowych lub końcowych .

ale wtedy i tylko wtedy, gdy jesteś w przypadku których nie można rozwiązać odpowiedź mingos musi być pomocą

+0

Myślę, że jest to wada projektowa. są bardzo złożone i wprowadzają modyfikacje, które mogą spowodować, że dane wejściowe będą nieważne, dlatego filtry powinny być podzielone na dwa typy: filtry normalizacji, które wymienisz, takie jak przycinanie, które należy uruchomić przed sprawdzaniem poprawności, i inne filtry, które powodują bardziej złożone modyfikacje. wybierz, kiedy dodajesz filtr, kiedy wyzwalać ten filtr – jblue

1

Co chcesz osiągnąć to, aby zmienić domyślne zachowanie jak element tekstowy jest przetwarzane. Dlatego myślę, że mógłbyś stworzyć swój własny element (np. My_Form_Element_Text), który rozszerza Zend_Form_Element_Text i przeładowuje jego metodę isValid().

W szczególności można po prostu zmienić drugą linię w oryginalnej metodzie isValid(), z $value = $this->getValue(); na $value = $this->getUnfilteredValue();. W ten sposób twoja walidacja zostanie przeprowadzona przy użyciu niefiltrowanych wartości.

+0

To jest interesujący pomysł. Jedyny problem, jaki widzę z tym, to że automatycznie tracę wszystkie pozostałe filtry. Jeśli zrobię modyfikację na wartości niefiltrowanej, to stracę na przykład filtr Trim, z tego powodu, jak na razie odpowiedź mingo prawdopodobnie daje pożądany efekt, chociaż nie podoba mi się to, że jest w kontrolerze. r może określić dokładną kolejność, jaką chce dla walidatorów i filtrów. – jblue

+0

@jblue. Więc chcesz mieć tylko jeden filtr zastosowany po walidacji, a reszta w normalny sposób, tak? Oczywiście można to jeszcze zrobić, tworząc niestandardowy element tekstowy. – Marcin

Powiązane problemy