昨日、ついにsymfonyの1.4がリリースされましたね。1.0同様、3年間の Long Term Support ということで、今後しばらくは1.4で落ち着くのかなぁ。。。と感じてるところです。
さて、symfonyでフォーム(sfForm)を作っていて常々感じるのは、POSTされたデータをそのままバリデートするのではなく、せめてmb_convert_kanaでフィルタ(正規化)した後にバリデートしたい、ということです。PEARのHTML_QuickFormでいうところのapplyFilter()の機能ですね。
ただしsfFormには上記のようなフィルタ機能がありません。そのため、私は既存のsfValidatorStringを継承して以下のカスタムバリデータを使ってます。symfony 1.2 で動作確認していますが、コードを見る限りでは1.3, 1.4でも問題なく使えるはずです。
サンプルコード
sfValidatorStringKana.class.php
<?php /* * This file is part of the symfony package. * (c) Fabien Potencier <fabien.potencier@symfony-project.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * sfValidatorStringKana validates a multibyte string. * * @package symfony * @subpackage validator * @author Yoshinori Ishii <ishii.yoshinori@itra.jp> * @version SVN: $Id$ */ class sfValidatorStringKana extends sfValidatorString { /** * Configures the current validator. * * Available options: * * * convert_option: Convert option for mb_convert_kana() * * @param array $options An array of options * @param array $messages An array of error messages * * @see sfValidatorString */ protected function configure($options = array(), $messages = array()) { parent::configure($options, $messages); $this->setOption('trim', true); $this->addOption('convert_option', 'asKV'); } /** * @see sfValidatorBase */ public function clean($value) { if ($this->hasOption('convert_option')) { $value = mb_convert_kana($value, $this->getOption('convert_option'), $this->getCharset()); } return parent::clean($value); } }
上記のコードをsfValidatorStringKana.class.phpとしてlib/以下にファイルを配置すればインストールは完了です。
フォームクラスからの呼び出し方は以下のサンプルの通り、sfValidatorStringとほぼ同じです。convert_optionはmb_convert_kanaの第2引数に渡す変換オプションです(デフォルトで'asKV'が設定されています)。
呼び出し方サンプル
$form->setValidators(array( 'name' => new sfValidatorStringKana(array( 'min_length' => 4, 'max_length' => 50, 'convert_option' => 'asKV', // mb_convert_kanaの変換オプション )), ));
clean()をオーバーライドした理由
既存のバリデータを見る限り、カスタムバリデータでオーバーライドされるべきメソッドはdoClean()なんですが、このクラスではdoClean()ではなくclean()をオーバーライドしています。あえてclean()をオーバーライドした理由は、sfValidatorBase::clean()で行われるデフォルトのバリデーション(trimや必須チェック)の前にフィルタリングを行いたかったからです。
例えば全角スペースのみを含む文字列がPOSTされた場合、doClean()をオーバーライドしただけだと、trimと必須チェックをすり抜けてしまうため、フィルタの意味を成さなくなってしまうのです。ここのところ、文字だとちょっとわかりづらいので、図でまとめてみました↓
doClean()をオーバーライドしたとき
clean()をオーバーライドしたとき
他にも使いまわしがききそうなカスタムバリデータを作ってる方がいらっしゃったら、コメントなどで教えてもらえるととてもうれしいです。