
昨日、ついに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()をオーバーライドしたとき
他にも使いまわしがききそうなカスタムバリデータを作ってる方がいらっしゃったら、コメントなどで教えてもらえるととてもうれしいです。
