2011-01-28 5 views
6

要素があります。私はそれにカスタムバリデータとカスタムフィルタを追加したいと思います。バリデーターは、入力がいくつかの許可された値の1つであることを確認した後、フィルターはいくつかのカスタム値を入力に追加します。これは、フィルタを実行する前に元の入力を最初に検証する必要があることを意味します。私はこの順序でそれを行う。このバリデータの後にこのフィルタを実行する方法

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

しかし、この順序は尊重されていない。フィルタが最初に実行され、データが変更されると、バリデータはフィルタ処理されたデータで実行されます。つまり、有効な入力に対しても常に失敗します。意図的な

注意であることをdocumentationからのようだ:検証前検証に提供 フィルタチェーンを通じて 値をZend_Form_Element ::のisValid() フィルター値を濾過で動作します。 の詳細については、 のフィルタセクションを参照してください。

バリデータとフィルタの実行順序を指定するにはどうすればよいですか?

答えて

7

確かに、検証後のフィルタリングをサポートするカスタム要素を作成するのが良い方法です。どのようにこの件について: - 薄いコントローラを維持これは、フォームでの検証とフィルタリングを保つ

$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(), 
    ), 
)); 

/** 
* 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; 
    } 
} 

使い方はこのようなものになるだろう。

テストされていません、暗闇の中で刺すだけです。そして確かに、キーを使ってフィルタを追加/削除するAPIを太ったり修正したりできます。

Whaddyaだと思いますか?

+0

+1。非常にいいですね。私はまた、setPostValidateFilters()メソッドがキー 'postValidateFilters'に対して自動的に(はい?)呼び出されることを知らなかった。 – Marcin

+0

@Marcin:私はそれがオプションが機能する方法だと思います。オプション名に「一致」するメソッドがある場合、そのメソッドは 'setOptions()'の間に呼び出されます。 –

+0

+1非常に優れた実装 – tawfekov

4

フィルターをまったく追加しないことがあります。コントローラに最初のコンテンツを検証し、その後、個別にフィルタを使用します。

$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 
} 

私はこれをやったことがないが、私はこの(または類似した何かが)うまくいくかもしれないと仮定します。

+0

+1可能な解決策ですが、わかりません。すべてがうまくいかない場合は、私はそれを行いますが、コントローラを薄くして、それが属するフォーム要素でフィルタリングロジックを保持したいと考えています。 – jblue

+0

確かに、私はフォームコードにもそれを保持したいと思いますが、バリデータとフィルタが呼び出される順序に影響を与える他の方法は考えられません。私はときどき何か他のものがチェックされ/満たされている場合にのみ、フィールドのセットが必要な場合など、理想的にはフォームに存在する必要があるものもコントローラに追加することがあります。クライアント側で、またはフォームを記入する前に、確実に確認することはできませんので、コントローラーで余分なフォームマジックを行うことが必要な場合もあります。( – mingos

1

良い点! 、

私の知る限りフィルタは、または入力を検証する前に実行する必要がありますする必要があります へ

それはしばしば有用かつ/または必要だZF docsから前の検証に入力 上のいくつかの正規化を行います。たとえば、 はすべてのHTMLを取り除きたい場合がありますが、 は、提出が有効であることを確認するために のままにしておきます。それとも あなたは StringLengthのバリデータが カウントが先行または 空白文字を付けずに入力の 正しい長さを使用するように、空のスペース 周囲の入力をトリミングすることもできます。

しかし、あなたはケースである場合にのみmingosの答えを解決できない場合は、あなたが達成したい何

+0

これは設計上の欠陥だと思います。バリデーションの前に実行する必要があるトリムや、より複雑な変更を行う他のフィルタなど2つのタイプに分類する必要があります。このフィルタをトリガするときにフィルタを追加するときに選択します – jblue

1

は、テキスト要素が処理されているかのデフォルトの動作を変更することで助けなければなりません。つまり、Zend_Form_Element_Textを拡張してisValid()メソッドをオーバーロードする独自の要素(My_Form_Element_Textなど)を作成することができると思います。

具体的には、元のisValid()メソッドの2行目を$value = $this->getValue();から$value = $this->getUnfilteredValue();に変更するだけです。この方法で、フィルタリングされていない値を使用して検証が実行されます。

+0

これは興味深い考えです。私が見るのは、他のすべてのフィルタを自動的に失うことだけです。フィルタリングされていない値を変更すると、このような理由から、これまでのところ、mingoの答えはコントローラにあるのが好きではありませんが、おそらく私の望む効果があります。 rは、バリデータとフィルタに必要な正確な順序を指定できます。 – jblue

+0

@jblue。したがって、検証後に1つのフィルタのみを適用したい場合は残りを通常の方法で適用したいのですか?これはもちろんカスタムテキスト要素を作成することによっても可能です。 – Marcin

関連する問題