Phalconモデルまとめ(4) バリデーションとイベント

「最速」PHPフレームワークPhalconのモデルについて、基本事項をまとめます(公式ドキュメントの翻訳+αです)。記事執筆時のPhalconのバージョンは1.3.1です。

バリデーションメッセージ

PhalconMvcModelには、INSERT/UPDATE時のバリデーションメッセージの保持・出力を柔軟に行えるサブシステムがあります。

それぞれのメッセージは、PhalconMvcModelMessageクラスのインスタンスになります。生成されたメッセージの集合は、getMessages()メソッドで取得することができます。それぞれのメッセージは、フィールド名やメッセージの種類のような、幅広い情報を提供します。

PhalconMvcModelが生成可能なメッセージの一覧は以下です。

種類 説明
PresenceOf フィールドにNOT NULL制約が付与されているときに、null値をINSERT/UPDATEしようとした際に発生
ConstrainvViolation 仮想外部キー制約を設定しているフィールドに、参照しているモデルに存在しない値をINSERT/UPDATEしようとした際に発生
InvalidValue 無効な値によってバリデーションが失敗した際に発生
InvalidCreateAttempt 既に存在するレコードを新規作成しようとした際に発生
InvalidUpdateAttempt 更新しようとしたレコードがまだ存在しない際に発生

getMessages()メソッドをオーバーライドすることで、モデルが自動で生成するメッセージを置き換えることができます。

イベントとイベントマネージャ

モデルには、INSERT/UPDATE/DELETE時に実行されるイベントを実装することができるようになっています。これらは、モデルのビジネスルールを定義する助けになります。PhalconMvcModelがサポートしているイベントの一覧は以下です(実行順)。

処理 イベント名 処理の中断可否 説明
INSERT/UPDATE beforeValidation フィールドのNOT NULL・空文字列・外部キー制約のバリデーション前に実行される
INSERT beforeValidationOnCreate INSERTの場合で、フィールドのNOT NULL・空文字列・外部キー制約のバリデーション前に実行される
UPDATE beforeValidationOnUpdate UPDATEの場合で、フィールドのNOT NULL・空文字列・外部キー制約のバリデーション前に実行される
INSERT/UPDATE onValidationFails ○(既に停止済み) バリデーションが失敗した際に実行される
INSERT afterValidationOnCreate INSERTの場合で、フィールドのバリデーション後に実行される
UPDATE afterValidationOnUpdate UPDATEの場合で、フィールドのバリデーション後に実行される
INSERT/UPDATE afterValidation フィールドのバリデーション後に実行される
INSERT/UPDATE beforeSave INSERT又はUPDATEの実行前に実行される
UPDATE beforeUpdate UPDATEの実行前に実行される
INSERT beforeCreate INSERTの実行前に実行される
UPDATE afterUpdate × UPDATEの実行後に実行される
INSERT afterCreate × INSERTの実行後に実行される
INSERT/UPDATE afterSave × INSERT/UPDATEの実行後に実行される

モデルのクラスにイベントを実装する

モデルをイベントに対応させるための最も簡単な方法は、イベント名と同じ名前のメソッドをモデルのクラスに実装することです。

イベントは、処理の実行前に値を代入するのに便利です。

イベントマネージャのカスタマイズ

モデルのイベントコンポーネントは、PhalconEventsManagerと統合されています。そのため、イベントが実行される際のリスナーを作ることもできます。

上記サンプルコードでは、イベントマネージャはオブジェクトとリスナーの橋渡しを行います。イベントは、Robotsモデルのsave時に発火します。

全てのオブジェクトに共通のEventsManagerを実装したい場合、EventsManagerをModelsManagerに登録します。

リスナーがfalseを返すと、その処理の実行は中断されます。

ビジネスルールを実装する

INSERT/UPDATE/DELETEの実行時に、モデルはイベント一覧に挙げられた名前のメソッドが無いか確認します。

以下のコード例では、INSERT/UPDATE時のイベントを実装し、yearの値が0未満でないかバリデーションしています。

イベントがfalseを返すと、処理は中断されます。イベントが何も返さない場合、PhalconMvcModelはtrueが返されたとみなします。

データの完全性バリデーション

PhalconMvcModelは、データをバリデーションし、ビジネスルールを実装するためのイベントを提供しています。「validation」イベントによって、組み込みのバリデーターを呼び出すことができます。Phalconは、いくつかの組み込みバリデーターを提供しています。

上記コード例では、組み込みの「InclusionIn」バリデーターを使用しています。このバリデーターは、「type」フィールドの値がdomainのリストに含まれているかチェックしています。値が含まれていなかった場合は、バリデーションに失敗し、バリデーターはfalseを返します。

組み込みのバリデーターの一覧は以下です。

名前 説明 実装例
PresenceOf フィールドの値がnullではなく、空文字列でもないことをバリデーションする。NOT NULL制約が設定されているフィールドに対しては、このバリデーターが自動的に追加される。
Email フィールドの値が有効なEメールアドレスであるかバリデーションする
ExclusionIn フィールドの値が禁止リストに含まれないことをバリデーションする
InclusionIn フィールドの値が許可リストに含まれることをバリデーションする
Numericality フィールドの値が数値形式かバリデーションする
Regex フィールドの値が正規表現にマッチするかバリデーションする
Uniqueness フィールドの値が既存のレコードと重複しないかバリデーションする
StringLength 文字列の長さをバリデーションする
Url フィールドの値が有効なURLの形式化バリデーションする

組み込みのバリデーターに加えて、独自のバリデーターを作成することもできます。

バリデーターをモデルに追加するには、以下のようにします。

バリデーターを作成することで、バリデーションのロジックを複数のモデルで使い回すことができます。1箇所でしか使わないバリデーションであれば、以下のようにシンプルに実装することもできます。

SQLインジェクションを避ける

モデルのプロパティに代入された値は全て、そのデータ型に応じたエスケープが施されます。開発者が、DBに入れる値のエスケープを実装する必要はありません。Phalconは内部でPDOのバインド機構を使用して、自動エスケープを行っています。

上記テーブルへのINSERTをする際、PDOを使用すると、以下のようなコードになります。

Phalconのモデルを使用すると、以下のように書けます(エスケープは全て自動で行われます)。

カラムをスキップする

何らかのトリガーや、デフォルト値の代入を行いたいため、バリデーションを行いたくない場合があります。モデルによるバリデーションを行わないようにするには、以下のように書きます。

これによって、アプリケーション全体で、INSERT/UPDATE時のバリデーションが実行されなくなります。デフォルト値の代入は以下のように行えます。

イベントのコールバックによって、特定条件の場合にデフォルト値を設定することもできます。

注意:PhalconDbRawValueは、ユーザー入力のような外部データや変数の値の代入に使用してはいけません。RawValueにはバインド機構が使用されないため、SQLインジェクション脆弱性を引き起こす危険性があります。

ダイナミックアップデート

SQLのUPDATE文は、デフォルトでは全てのカラムをUPDATEするように作成されます。ダイナミックアップデートを有効化すると、変更されたフィールドだけが更新されるUPDATE文が生成されます。

これによって、アプリケーションサーバ・DBサーバ間のトラフィックが減少し、パフォーマンスが改善されることがあります。特に、BLOB/TEXT型のような大きなデータを取り扱うカラムがある場合、ダイナミックアップデートは大きな助けになります。

レコードの削除

PhalconMvcModel::delete()メソッドに寄って、レコードを削除できます。

結果セットをforeachでまわすことで、複数のレコードを削除できます。

以下のイベントを使用することで、削除処理の際に実行されるビジネスルールを定義することができます。

処理 名前 処理の中断可否 説明
DELETE beforeDelete 削除処理の実行前に実行
DELETE afterDelete × 削除処理の実行後に実行

上記イベントを使用すると、以下のようにビジネス・ルールを定義できます。

バリデーション失敗時のイベント

バリデーション失敗時のイベントもあります。

処理 名前 説明
INSERT/UPDATE notSave INSERT/UPDATEが何からの理由で失敗した際に発生
INSERT/UPDATE/DELETE onValidationFails データ処理が失敗した際に発生

今回はここまで

ここまで、Phalconのモデルを利用したバリデーションの実装方法をみてきました。次回は、Behaviorsから先をみていきます。

コメントを残す