SymfonyはYAMLを使ってvalidationを設定することができます。詳しい説明に関しては本家のドキュメントを参照してください。
HTML_QuickFormというものをご存知でしょうか?
ルールやフィルタを設定してFormで送信された値の入力のチェックをおこなうことができます。 ルールは送信された値の入力規則にあたります。 フィルタは送信された値から余計な文字の削除や変換をおこなう機能です。 例えばtrimなどをactionで毎回書く作業をフィルタを実装することで省くことができます。
Symfonyではvalidationクラスを作成することで様々な入力規則の作成が可能です。 QuickFormでいうルールに対して対応していますが、フィルタには対応していません。
validationを利用してtrimとmbConvertKanaのフィルタを実装してみます。
例 update.yml
methods: get: [name] post: [name] names: name: required: Yes required_msg: "名前を入力してください。" validators: trim, mbConvertKana trim: class: myTrimFilter param: form_id: name error_msg: "名前を入力してください。"; mbConvertKana: class: myMbConvertKanaFilter param: form_id: name option: "KVa"
説明を簡単にするために”name”のみを記述しました。
Formで”name”が送信された時に値が入っていれば必ずvalidationが呼ばれます。 validatorsにtrim, mbConvertKanaとすることで trim → mbConvertKana を順番にかけることができます。 mbConvertKana, trim と記述すれば mbConvertKana → trim の順番にすることもできます。
ではtrimとmbConvertKanaが具体的にどのような処理をおこなうのか説明します。
myTrimFilter
trim:
class: myTrimFilter
param:
form_id: name
error_msg: "名前を入力してください。";trimの中身にclass:myTrimFilterとクラスが指定されています。 リクエストされた値に対してtrimをおこなうFilterなのですがValidatorの機能を利用して実装しています。 機能的にFilterなのでmyTrimFilter.class.phpとしています。
次にパラメータとしてform_id,error_msgを指定します。 trimをかけるリクエストが”name”なのでnameを指定します。
送信された値が全てスペースで埋まっていた場合、NULLではないのでrequired:Yesではエラーになりません。 error_msgはtrimの結果で文字列がNULLになる場合があるのでその時のメッセージです。
またtrim関数では半角スペースにしか対応していないので正規表現を使って全角のスペースも対応しています。
<?php class myTrimFilter extends sfValidator { public function execute (&$value, &$error) { //正規表現で全角スペースを半角にする mb_regex_encoding("UTF-8"); $value = mbereg_replace('^[ *]','',$value); $value = mbereg_replace('[ ]*$ ','',$value); //trim $value = trim($value); if(strlen($value) > 0 ){ //リクエストに値をセットする $_param = $this->getParameterHolder()->get('form_id'); $this->getContext()->getRequest()->setParameter($_param,$value); return true; }else{ $error = $this->getParameterHolder()->get('error_msg'); return false; } } public function initialize ($context, $parameters = null) { // initialize parent parent::initialize($context); $this->getParameterHolder()->set('error_msg', 'Invalid input'); $this->getParameterHolder()->add($parameters); return true; } } ?>
myMbConvertKanaFilter
mbConvertKana:
class: myMbConvertKanaFilter
param:
form_id: name
option: "KVa"日本語を使う上で一番考慮が必要だと思い作成しました。
基本的にmyTrimFilterと同じ方法でmyMbConvertKanaFilter.class.phpを実装しました。
パラメータにoptionはPHPの関数mb_convert_kanaを参照してください。
<?php class myMbConvertKanaFilter extends sfValidator { public function execute (&$value, &$error) { //mb_convert_kana $option = $this->getParameterHolder()->get('option'); $value = mb_convert_kana($value,$option,"UTF-8"); //リクエストに値をセットする $_param = $this->getParameterHolder()->get('form_id'); $this->getContext()->getRequest()->setParameter($_param,$value); return true; } public function initialize ($context, $parameters = null) { // initialize parent parent::initialize($context); $this->getParameterHolder()->set('error_msg', 'Invalid input'); $this->getParameterHolder()->add($parameters); return true; } } ?>
最後にtrim、mbConvertKana両方ともform_idを指定する必要について説明します。 通常のvalidationであれば値をチェックしてtrue,falseを返しfalseであればエラーを表示します。
しかし、trimやmbConvertKanaはFilterとして機能しているので結果を保持しなくていけません。 form_idでリクエストの名前を渡し、その名前を使って結果をリクエストにセットしています。


何となく思ったのですが、Symfony Book p.259にあるconvertersは使えないですか?
You might want to transform the values entered by the user before putting them in a form input. Escaping, url rewriting, transformation of special characters into entities, etc., all the transformations that can be called through a function (existing or defined by you) can be applied to the fields of your form if you define the transformation under the converters: key: fillin: activate: on param: name: test converters: # converters to apply htmlentities: [first_name, comments] htmlspecialchars: [comments]
convertersいけてる。それ知りませんでした!
ちなみに上のeregでは半角スペースの後に全角スペースがあると困ります それと、eregよりpregの方が早いみたいです
この方法だと複数の項目にフィルターをかけるのが面倒じゃないですか? 例えば name のほかに mail の項目を作ったとします。 name と mail の両方に trim する場合、 form_id: の値を変えて trim を2回書かなきゃだめですよね。
trim: class: myTrimFilter param: form_id: name
trim: class: myTrimFilter param: form_id: mail
項目の数がもっと多いときは、ちょっとしんどいですね。 何かいい方法はないものか…
fillinのconvertersはなかなか良いのですが、 フィルタリングの処理が、validatorの後になるみたいですね。 この順序は変更できるんでしょうかね?
バリデーションの前にfillinのconvertersのような処理ができるよう、本体に手を入れてみました。 http://www.symfony-project.com/trac/ticket/759
myTrimFilter.class.phpの中で ymlで設定した trim: class: myTrimFilter param: form_id: name error_msg: "名前を入力してください。";
form_idをなんとか拾えませんでしょうか。 registerValidatorメソッドで設定してるみたいですね。 いろいろ試してみましがが、だめでした。