Zend_Filter_Input(日本語)Zend_Filter_Input は宣言型のインターフェイスです。 複数のフィルタやバリデータを関連付け、それをデータの集合に適用し、 そのフィルタやバリデータで処理した後の結果を取得できます。 デフォルトでは、HTML 出力に適した形式にエスケープされた結果を返します。 このクラスは、外部からのデータのための「檻」と考えるとよいでしょう。 アプリケーションの外部から渡されたデータとは、たとえば HTTP リクエストのパラメータや HTTP ヘッダ、ウェブサービス、 データベースから読み込んだデータや他のファイルから読み込んだデータなどのことです。 これらのデータはいったん檻の中に閉じ込められます。 それ以降、アプリケーションからこれらのデータにアクセスするには、 看守に対して「そのデータが何であって、何の目的で使用するのか」 を説明しなければならなくなります。看守はその説明の内容に応じてデータの妥当性を検証します。 状況に応じて、適切にデータのエスケープも行います。 これらの処理を終えたデータしか、檻の中から外に出ることができません。 シンプルで便利なインターフェイスを提供することで、 開発者がよりよいプログラミング習慣を身につけられるようにします。 また、データの利用法について常に気をつけられるようにします。
Zend_Filter_Input は、以下の手順で使用します。
以下のセクションでは、このクラスの使用法について順を追って説明していきます。 フィルタルールおよび検証ルールの宣言Zend_Filter_Input のインスタンスを作成する前に、 フィルタルールと検証ルールの配列を宣言します。 これらの連想配列は、ルールの名前を フィルタやバリデータの名前、 あるいはフィルタチェインやバリデータチェインの名前と関連付けるものです。 次の例のフィルタルールは、'month' フィールドを Zend_Filter_Digits でフィルタリングし、'account' フィールドを Zend_Filter_StringTrim でフィルタリングすることを表します。 また、検証ルールでは、'account' フィールドには英字のみを許可することを指定しています。
ルールの定義方法には、いくつかの方式があります。
ルールのキーとして、特別な "ワイルドカード" 文字 '*' を使用してフィルタ配列やバリデータ配列を作成できます。 このルールで宣言したフィルタやバリデータは、 すべての入力フィールドに適用されます。 フィルタ配列やバリデータ配列内のエントリの並び順には意味があることに注意しましょう。 ルールは、それを宣言した順に適用されます。
フィルタおよびバリデータの処理装置の作成フィルタやバリデータの配列を宣言したら、 それを Zend_Filter_Input のコンストラクタの引数で指定します。 その結果、すべてのフィルタリング規則と検証規則を知っているオブジェクトが返されます。 このオブジェクトを使用して、入力データを処理していきます。
入力データは、コンストラクタの第三引数として指定できます。
このデータは、連想配列形式で指定します。フィールド名が連想配列のキー、
それに対応する値がデータの値となります。PHP が標準機能として提供している
あるいは、 setData() メソッドを使用してデータを渡すこともできます。 ここで渡すデータの形式は、先ほど説明したのと同じ形式の連想配列となります。
setData() メソッドは、既存の Zend_Filter_Input オブジェクトに対して フィルタルールや検証ルールはそのままで別の入力データを再定義できます。 このメソッドを使用すると、同じルールを 複数の異なる入力データに対して適用できます。 検証済みのフィールドやその他の結果情報の取得フィルタやバリデータを宣言し、入力処理装置を作成したら、 次はその結果を取得する番です。存在しないフィールド、 未知のフィールド、無効なフィールドなどの情報のほかに、 フィルタを適用した後の値を含むフィールドの内容も取得できます。 入力が妥当かどうかの問い合わせすべての入力データがバリデーションルールを通過すると、 isValid() メソッドは TRUE を返します。 無効な形式の入力や必須フィールドの未入力がひとつでもあると、 isValid() は FALSE を返します。
このメソッドには、オプションで文字列の引数を指定できます。 ここには、フィールドの名前を指定します。 指定したフィールドがバリデーションを通過して取得可能になると、 isValid('fieldName') は TRUE を返します。
無効なフィールド、存在しないフィールド、未知のフィールドの取得
getMessages() メソッドの返り値は連想配列となります。 ルール名と、そのルールに関連するエラーメッセージの配列を関連付けたものです。 この配列のインデックスは、ルールを宣言したときに使用したルール名であることに注意しましょう。 これは、そのルールによるチェックを行ったフィールド名とは異なります。 getMessages() メソッドが返す配列は、 getInvalid() と getMissing() の結果をマージしたものとなります。 これらのメソッドは、それぞれバリデーションに失敗したときのメッセージと 必須入力項目が未入力の場合のメッセージを返すものです。 getErrors() メソッドは、 ルールの名前とエラー ID の配列を対応させた連想配列を返します。 エラー ID は固定文字列で、検証に失敗した原因を表します。 エラーメッセージは変更可能です。詳細は この節 を参照ください。 getMissing() が返すメッセージは、オプション 'missingMessage' で指定できます。 これは、Zend_Filter_Input のコンストラクタへの引数か、あるいは setOptions() メソッドで指定します。
Zend_Filter_Input によって返されるメッセージで、 複数の言語を提供できるようにするトランスレータも追加できます。 アプリケーション全体のトランスレータを使っているときは、 それは Zend_Filter_Input でも使われます。 この場合、手動でトランスレータを設定する必要はありません。 getUnknown() メソッドの結果は、 フィールド名とフィールドの値を対応させた連想配列となります。 ここで配列のキーとして使われるのはフィールド名であり、 ルールの名前ではありません。 どれが未知のフィールドなのかを表すのに、ルール名では具合が悪いからです。 有効なフィールドの取得無効でもなければ存在しないわけでもなく、 かつ未知でもないフィールドが、有効なフィールドとみなされます。 有効なフィールドの値を取得するためのマジックメソッドが用意されています。 また、それ以外にも getEscaped() および getUnescaped() というメソッドがあります。
デフォルトでは、値を取得する際には Zend_Filter_HtmlEntities によるフィルタリングが行われます。 これがデフォルトとなっている理由は、ほとんどの場合は フィールドの値を HTML に出力するであろうと考えられるからです。 HtmlEntities フィルタを使用すると、 HTML に予期せぬ出力が現れないようにして セキュリティ上の問題を防ぎます。
Warning
検証していないフィールドのエスケープ先ほど説明したように、 getEscaped() が返すのは検証済みのフィールドだけです。 バリデータに関連づけられていないフィールドは、この方法では取得できません。 しかし、それを解決する方法もあります。 何もしないバリデータをすべてのフィールドに追加すればいいのです。 この方式はセキュリティ面で問題があり、 クロスサイトスクリプティング攻撃に使われる可能性があることに注意しましょう。 各フィールドに対して個別にバリデータを設定しておくべきです。 別のフィルタによるエスケープを行うことも可能です。 その場合は、それをコンストラクタのオプション配列で指定します。
あるいは、 setDefaultEscapeFilter() メソッドを使用することもできます。
どちらの場合についても、エスケープフィルタの指定方法は フィルタクラスのベース名を表す文字列かフィルタクラスのインスタンスの いずれかとなります。エスケープフィルタとして使用できるのは、 フィルタチェインのインスタンスか Zend_Filter クラスのオブジェクトです。
出力をエスケープするフィルタは、このように
バリデーションの終了後に適用しなければなりません。
フィルタルールで指定したその他のフィルタは、
バリデーションの前に適用されます。
エスケープフィルタをバリデーションの前に適用してしまうと、
バリデーション作業がより複雑になってしまい、
エスケープ前の値とエスケープ後の値を両方管理するのが難しくなります。
出力をエスケープするフィルタは、 getEscaped() というメソッドがひとつあるだけなので、 エスケープ用のフィルタはひとつだけしか指定できません (とはいえ、そのフィルタとしてフィルタチェインを指定することもできます)。 ひとつの Zend_Filter_Input のインスタンスから 複数のフィルタリングメソッドの結果を返したい場合は、 Zend_Filter_Input を継承したサブクラスで新しいメソッドを実装して対応しましょう。 メタコマンドによるフィルタルールやバリデータルールの制御フィールドとフィルタやバリデータの対応を宣言するのに加えて、 配列を宣言する際に "メタコマンド" を指定できます。 これは、Zend_Filter_Input の挙動を制御するオプションです。 メタコマンドは、フィルタ配列やバリデータ配列の値として指定する 文字列インデックスのエントリとなります。 FIELDS メタコマンドフィルタやバリデータの名前がそれを適用するフィールドの名前と異なる場合は、 'fields' メタコマンドでフィールド名を指定できます。 このメタコマンドを指定する際に、文字列ではなくクラス定数 Zend_Filter_Input::FIELDS を使用できます。 上の例では、'digits' フィルタを 'mo' という名前の入力フィールドに適用しています。 文字列 'month' は、単なるこのフィルタリングルールのニモニックキーとなります。 'fields' メタコマンドでフィールドを指定した場合は、 これはフィールド名としては使われず、単なるルール名となります。 'fields' メタコマンドのデフォルト値は、現在のルールのインデックスとなります。 上の例の場合は、'fields' メタコマンドを指定しなかった場合は、 'month' という名前のフィールドにこのルールが適用されます。 'fields' メタコマンドのもうひとつの使用法は、 複数のフィールドの入力を要求するフィルタやバリデータで フィールドを指定することです。 'fields' メタコマンドに配列を指定すると、 指定したフィールドの配列がフィルタやバリデータへの引数となります。 たとえば、パスワードを登録する場合に、ふたつのフィールドに入力させて その値が一致することを確認するなどといった処理は、よくあるものです。 配列の引数を受け取り、それらの入力フィールドの値が等しいときにだけ TRUE を返すバリデータを考えてみましょう。 このルールのバリデーションに失敗した場合は、 getInvalid() の返り値はルールのキー ('password') となります。'fields' メタコマンドのフィールド名は用いられません。 PRESENCE メタコマンドバリデータ配列の各エントリでは、メタコマンド 'presence' を指定できます。 このメタコマンドの値が 'required' の場合は、 そのフィールドの値が必須となります。 未入力の場合は「存在しないフィールド」として報告されます。 このメタコマンドを指定する際に、文字列ではなくクラス定数 Zend_Filter_Input::PRESENCE を使用できます。 このメタコマンドのデフォルト値は 'optional' です。 DEFAULT_VALUE メタコマンド入力データにそのフィールドが存在しない場合に、もしメタコマンド 'default' がルールで指定されていれば そのメタコマンドの値がフィールドの値となります。 このメタコマンドを指定する際に、文字列ではなくクラス定数 Zend_Filter_Input::DEFAULT_VALUE を使用できます。 このデフォルト値は、バリデータを適用する前にフィールドの代入されます。 また、そのフィールドのデフォルト値は現在のルールでのみ適用されます。 もしそのフィールドが別のルールから参照されていた場合には、 別のルールを評価する際にはそのフィールドには値が入っていないことになります。 つまり、個々のルールで別々のデフォルト値を宣言できるということです。
このメタコマンドにはデフォルト値はありません。 ALLOW_EMPTY メタコマンドデフォルトでは、入力データ中にフィールドが存在すれば、 たとえそれが空文字列 ('') であったとしてもバリデータを適用します。 その結果、検証に失敗することもありえます。 たとえば、数値かどうかを調べるバリデータは、 空文字列を通すとエラーを報告します。 空の文字列 (長さゼロの文字列) の中には文字が含まれないので、 数値を表す文字も含まれないからです。 空の文字列も有効であるとみなしたい場合は、メタコマンド 'allowEmpty' を TRUE に設定します。 すると、入力データとして空の文字列が渡された場合も検証を通過します。 このメタコマンドを指定する際に、文字列ではなくクラス定数 Zend_Filter_Input::ALLOW_EMPTY を使用できます。 このメタコマンドのデフォルト値は FALSE です。 非常に珍しいケースですが、バリデータは一切登録せずにメタコマンド 'allowEmpty' を FALSE (つまり、空の値は無効とみなす) と設定した検証ルールを定義すると、 Zend_Filter_Input はデフォルトのエラーメッセージを返します。 このメッセージは getMessages() で取得できます。 このメッセージは、'notEmptyMessage' オプションで設定します。 このオプションは、Zend_Filter_Input のコンストラクタへの引数か、 あるいは setOptions() メソッドで指定します。
BREAK_CHAIN メタコマンドデフォルトでは、ひとつのルールに複数のバリデータが登録されている場合は それをすべて適用し、すべてのエラーメッセージが結果のメッセージに含まれるようになります。 一方、メタコマンド 'breakChainOnFailure' を TRUE とすると、 どれかひとつのバリデータが失敗すると、 その時点でバリデータチェインが終了するようになります。 チェイン内のそれ以降のバリデータによる入力チェックは行いません。 つまり、指摘されたエラーを修正したとしても、 さらに別のエラーが発生する可能性があるということです。 このメタコマンドを指定する際に、文字列ではなくクラス定数 Zend_Filter_Input::BREAK_CHAIN を使用できます。 このメタコマンドのデフォルト値は FALSE です。 バリデータチェインクラスである Zend_Validate は、チェインの実行を中断できるという点で Zend_Filter_Input よりも柔軟です。 バリデータチェインクラスでは、チェイン内のバリデータのひとつが失敗したときに 即時に処理を終了させるオプションが設定できます。 Zend_Filter_Input の場合は、メタコマンド 'breakChainOnFailure' の設定がルール内のすべてのバリデータに適用されます。 より柔軟にしたい場合は、バリデータチェインを自前で作成して それをバリデータルールの定義時に指定します。
MESSAGES メタコマンドルール内の個々のバリデータのエラーメッセージを指定するには、メタコマンド 'messages' を使用します。このメタコマンドの値には、さまざまなものが指定できます。 たとえばひとつのルールの中に複数のバリデータがある場合に それぞれ別のメッセージを指定したり、 指定したバリデータで特定のエラー条件のときにのみ指定したメッセージを返したりといったことが考えられます。 このメタコマンドを指定する際に、文字列ではなくクラス定数 Zend_Filter_Input::MESSAGES を使用できます。 以下に示すのは、あるバリデータにデフォルトのエラーメッセージを設定する例です。 エラーメッセージを設定したいバリデータが複数ある場合は、 'messages' メタコマンドの値として配列を指定します。 この配列の各要素は、それぞれ同じインデックスのバリデータに適用されます。 つまり、n 番目のバリデータのメッセージを指定するには 配列のインデックスに n を指定します。 これを使用して、チェイン内の特定のバリデータにだけメッセージを設定して それ以外はデフォルトのメッセージを使用するということができます。 ひとつのバリデータに複数のエラーメッセージが存在する場合は、 メッセージのキーで識別します。 各バリデータクラスにはそれぞれ異なるキーが存在し、そのキーを用いて それぞれのバリデータクラスが生成するエラーメッセージを識別します。 バリデータクラスでは、メッセージのキーに対応する定数が定義されています。 これらのキーを 'messages' メタコマンドで使用できます。 この場合、文字列ではなく連想配列形式で渡します。
各バリデータクラスがエラーメッセージを複数持っているかどうかや それらのメッセージのキー、そしてメッセージのテンプレートで使用できるトークン 等についての情報については、各バリデータクラスのドキュメントを参照ください。 検証ルールのなかにバリデータがひとつだけしかない場合、 あるいはすべてのバリデータで同じメッセージセットを使用する場合は、 配列構造で追加しなくても参照できます。 オプションの使用による、全ルールへのメタコマンドの設定
メタコマンド 'allowEmpty' や 'breakChainOnFailure'、
'presence' の全ルール共通のデフォルト値は、
Zend_Filter_Input のコンストラクタの引数 メタコマンド 'fields'、'messages' と 'default' については、 このテクニックを使うことができません。 フィルタクラスへの名前空間の追加デフォルトでは、フィルタやバリデータを文字列で指定した場合は、 対応するクラスを Zend_Filter 名前空間あるいは Zend_Validate 名前空間から探します。 たとえば、文字列 'digits' でフィルタを指定すると、 Zend_Filter_Digits クラスを探すことになります。 独自のフィルタクラスやバリデータクラスを作成したり、 サードパーティのフィルタやバリデータを使用したりする場合は、 そのクラスの名前空間は Zend_Filter や Zend_Validate とは異なるでしょう。 その場合は、Zend_Filter_Input に別の名前空間を通知できます。 名前空間は、コンストラクタのオプションで指定できます。
あるいは、 addValidatorPrefixPath($prefix, $path) メソッドや addFilterPrefixPath($prefix, $path) メソッドを使うこともできます。 これらは、Zend_Filter_Input が使うプラグインローダへの直接のプロキシとなります。
名前空間 Zend_Filter と Zend_Validate は削除することができません。 新しい名前空間を追加することだけが可能となっています。 追加した名前空間を先に探し、Zend 名前空間を最後に探すという順序になります。
|