Zend_Filter_Input を使ってみる

入力した値のバリデーションには Zend_Validate_* を使用すると簡単に入力チェックができる。
例えば、hoge という入力フォームがあって、そこは必須で、4文字以上10文字未満なんて条件を書くと以下のようになる。

<?php
$param = $this->_getParam('hoge');
require_once 'Zend/Validate.php';
// My_Validate_NotEmpty は Zend_Validate_NotEmpty を継承したクラス
// 0 を Null と判定しない
require_once 'My/Validate/NotEmpty.php';
require_once 'Zend/Validate/StringLength.php';
$validateEmpty = new My_Validate_NotEmpty();
$validateEmpty->setMessage('hoge は必須です。');
$validateStringLength = new Zend_Validate_StringLength(4, 10);
$validateStringLength->setMessage('4文字以上10文字以下で入力して下さい。');
$chain = new Zend_Validate();
$chain->addValidator($validateEmpty)
            ->addValidator($validateStringLength);
if (!$chain->isValid($param)) {
     $this->_request->setParam("error", $chain->getMessages());
}

バリデータをチェインとして登録して一気に入力チェックを行ってくれる。


簡単なフォームならこれでも良いかもしれないが、入力チェックなんてフォームがある限り行うし、毎回毎回上記のようなコードを書くのは美しくない。
通化したい!と思いドキュメントを読んでみたら、Zend_Filter_Input を使えば実現できそう。

Zend_Filter_Input は宣言型のインターフェイスです。 複数のフィルタやバリデータを関連付け、それをデータの集合に適用し、 そのフィルタやバリデータで処理した後の結果を取得することができます。 デフォルトでは、HTML 出力に適した形式にエスケープされた結果を返します。

http://framework.zend.com/manual/ja/zend.filter.input.html

というわけで、Zend_Filter_Input を使って、バリデーションのルールだけコントローラに書いて、そのルールを登録すれば自動的に入力チェックが掛かるようなコードを書いてみた。

コントローラの親クラス

<?php
abstract protected function setRules();

protected function validate()
{
    $this->setRules();
   
     // ルールが記述されてない場合はチェックしないで true を返す
     if (!is_array($this->_rules)) {
         return true;
     }
     // フィルタは Null
     $inputs = new Zend_Filter_Input($this->_filters, $this->_rules);

     $data = $this->_getAllParams();        
     $ret = $inputs->setOptions(array('breakChainOnFailure' => false))
                ->setData($data)
                ->isValid();

     if ($ret === false) {
        $this->_request->setError('error', $inputs->getMessages());
     }
     return $ret;
}

コントローラ

<?php
protected function setRules()
{   
    require_once 'Zend/Validate/StringLength.php';
    require_once 'My/Validate/NotEmpty.php';
    $validations = array(
        'hoge' => array(
            new My_Validate_NotEmpty(),
            new Zend_Validate_StringLength(4, 10),
            'messages' => array(
                0 => 'hoge は必須です。',
                1 => '4文字以上10文字以下で入力して下さい。'
            )
        )
    );
   $this->_rules = $validations;
   return $this;
}

上記のようなコードをコントローラの親クラス(入門のチュートリアルとかでは Zend_Controller_Action から継承してコントローラを書いてあるけど、自分は Zend_Controller_Action を継承した子クラスをコントローラの親クラスとしてる)に記述した。
で、コントローラの親クラスの preDispatch() で validate() をコールして、false ならエラーを表示するようにした。


これでコントローラ側ではバリデーションのルールのみ記述すれば良い。
やはりこういうオレオレフレームワークもどきを作るには Zend Framework は便利。