バリデーション
Phalcon\Validation is an independent validation component that validates an arbitrary set of data. このコンポーネントを使用して、モデルまたはコレクションに属していないデータオブジェクトに対するバリデーションルールを実装できます。
次の例は、その基本的な使い方を示しています:
<?php
use Phalcon\Validation;
use Phalcon\Validation\Validator\Email;
use Phalcon\Validation\Validator\PresenceOf;
$validation = new Validation();
$validation->add(
'name',
new PresenceOf(
[
'message' => 'The name is required',
]
)
);
$validation->add(
'email',
new PresenceOf(
[
'message' => 'The e-mail is required',
]
)
);
$validation->add(
'email',
new Email(
[
'message' => 'The e-mail is not valid',
]
)
);
$messages = $validation->validate($_POST);
if (count($messages)) {
foreach ($messages as $message) {
echo $message, '<br>';
}
}
このコンポーネントは疎結合に設計されているため、フレームワークが提供するバリデータとともに独自のバリデータを作成することができます。
バリデーションの初期化
Validation chains can be initialized in a direct manner by just adding validators to the Phalcon\Validation object. コードと構成を再利用しやすくするために、バリデーションを別々のファイルに入れることができます:
<?php
use Phalcon\Validation;
use Phalcon\Validation\Validator\Email;
use Phalcon\Validation\Validator\PresenceOf;
class MyValidation extends Validation
{
public function initialize()
{
$this->add(
'name',
new PresenceOf(
[
'message' => 'The name is required',
]
)
);
$this->add(
'email',
new PresenceOf(
[
'message' => 'The e-mail is required',
]
)
);
$this->add(
'email',
new Email(
[
'message' => 'The e-mail is not valid',
]
)
);
}
}
次に、独自のバリデータを初期化して使用します:
<?php
$validation = new MyValidation();
$messages = $validation->validate($_POST);
if (count($messages)) {
foreach ($messages as $message) {
echo $message, '<br>';
}
}
バリデーター
Phalconは下記のような組み込みバリデーター一式をコンポーネントとして公開しています:
次の例では、コンポーネントにどうやってバリデーターを作成するかを説明します。
<?php
use Phalcon\Validation;
use Phalcon\Validation\Message;
use Phalcon\Validation\Validator;
class IpValidator extends Validator
{
/**
* バリデーションの実行
*
* @param Validation $validator
* @param string $attribute
* @return boolean
*/
public function validate(Validation $validator, $attribute)
{
$value = $validator->getValue($attribute);
if (!filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
$message = $this->getOption('message');
if (!$message) {
$message = 'The IP is not valid';
}
$validator->appendMessage(
new Message($message, $attribute, 'Ip')
);
return false;
}
return true;
}
}
バリデーターは、検証が成功したかどうかを示す有効なブール値を返すことが重要です。
Callbackバリデーター
By using Phalcon\Validation\Validator\Callback you can execute custom function which must return boolean or new validator class which will be used to validate the same field. true
を返すことでバリデーションが成功し、false
を返すとバリデーションが失敗したことを意味します。 このバリデータを実行するときにPhalconはそれが何であるかに応じてデータを渡します。エンティティ(例えば、モデル、stdClass
など)であればエンティティが渡され、そうでなければデータ(例えば$_POST
のようなArray)が渡されます。 例を示します:
<?php
use \Phalcon\Validation;
use \Phalcon\Validation\Validator\Callback;
use \Phalcon\Validation\Validator\PresenceOf;
$validation = new Validation();
$validation->add(
'amount',
new Callback(
[
'callback' => function($data) {
return $data['amount'] % 2 == 0;
},
'message' => 'Only even number of products are accepted'
]
)
);
$validation->add(
'amount',
new Callback(
[
'callback' => function($data) {
if($data['amount'] % 2 == 0) {
return $data['amount'] != 2;
}
return true;
},
'message' => "You can't buy 2 products"
]
)
);
$validation->add(
'description',
new Callback(
[
'callback' => function($data) {
if($data['amount'] >= 10) {
return new PresenceOf(
[
'message' => 'You must write why you need so big amount.'
]
);
}
return true;
}
]
)
);
$messages = $validation->validate(['amount' => 1]); // will return message from first validator
$messages = $validation->validate(['amount' => 2]); // will return message from second validator
$messages = $validation->validate(['amount' => 10]); // will return message from validator returned by third validator
バリデーションメッセージ
Phalcon\Validation has a messaging subsystem that provides a flexible way to output or store the validation messages generated during the validation processes.
Each message consists of an instance of the class Phalcon\Validation\Message. getMessages()
メソッドで、生成されたメッセージのセットが取得できます。 各メッセージは、メッセージを生成した属性やメッセージの種類のような拡張情報を提供します。
<?php
$messages = $validation->validate();
if (count($messages)) {
foreach ($messages as $message) {
echo 'Message: ', $message->getMessage(), "\n";
echo 'Field: ', $message->getField(), "\n";
echo 'Type: ', $message->getType(), "\n";
}
}
message
パラメータを渡すと、各バリデータのデフォルトメッセージを変更/変換できます。それから、メッセージのワイルドカード:field
をフィールドのラベルに置き換えることもできます:
<?php
use Phalcon\Validation\Validator\Email;
$validation->add(
'email',
new Email(
[
'message' => 'The e-mail is not valid',
]
)
);
By default, the getMessages()
method returns all the messages generated during validation. You can filter messages for a specific field using the filter()
method:
<?php
$messages = $validation->validate();
if (count($messages)) {
// フィールド 'name'に対して生成されたメッセージだけに絞ります
$filteredMessages = $messages->filter('name');
foreach ($filteredMessages as $message) {
echo $message;
}
}
データのフィルタリング
バリデーションの前にデータをフィルタリングして、悪意のあるデータまたは不正確なデータが処理されないようにできます。
<?php
use Phalcon\Validation;
$validation = new Validation();
$validation->add(
'name',
new PresenceOf(
[
'message' => 'The name is required',
]
)
);
$validation->add(
'email',
new PresenceOf(
[
'message' => 'The email is required',
]
)
);
// 余分なスペースを除去
$validation->setFilters('name', 'trim');
$validation->setFilters('email', 'trim');
Filtering and sanitizing is performed using the filter component. You can add more filters to this component or use the built-in ones.
バリデーションイベント
バリデーションがクラスで構成されている場合、beforeValidation()
メソッドおよびafterValidation()
メソッドを実装して、追加のチェック、フィルタ、クリーンアップなどを実行できます。 beforeValidation()
メソッドがfalseを返す場合、バリデーションは自動的にキャンセルされます。
<?php
use Phalcon\Validation;
class LoginValidation extends Validation
{
public function initialize()
{
// ...
}
/**
* バリデーションの前に実行
*
* @param array $data
* @param object $entity
* @param Phalcon\Validation\Message\Group $messages
* @return bool
*/
public function beforeValidation($data, $entity, $messages)
{
if ($this->request->getHttpHost() !== 'admin.mydomain.com') {
$messages->appendMessage(
new Message('Only users can log on in the administration domain')
);
return false;
}
return true;
}
/**
* バリデーションの後に実行
*
* @param array $data
* @param object $entity
* @param Phalcon\Validation\Message\Group $messages
*/
public function afterValidation($data, $entity, $messages)
{
// ... メッセージを追加したり、もっとバリデーションを追加したり
}
}
バリデーションのキャンセル
デフォルトでは、フィールドに割り当てられたすべてのバリデータは、いずれかが失敗したかどうかに関係なくテストされます。 この動作を変更するには、バリデーションコンポーネントが処理を中止する可能性のあるバリデーションを指定します:
<?php
use Phalcon\Validation;
use Phalcon\Validation\Validator\Regex;
use Phalcon\Validation\Validator\PresenceOf;
$validation = new Validation();
$validation->add(
'telephone',
new PresenceOf(
[
'message' => 'The telephone is required',
'cancelOnFail' => true,
]
)
);
$validation->add(
'telephone',
new Regex(
[
'message' => 'The telephone is required',
'pattern' => '/\+44 [0-9]+/',
]
)
);
$validation->add(
'telephone',
new StringLength(
[
'messageMinimum' => 'The telephone is too short',
'min' => 2,
]
)
);
最初のバリデータにはtrue
の値を持つcancelOnFail
オプションがあります。したがって、バリデータが失敗した場合、チェーン内の残りのバリデータは実行されません。
カスタムバリデータを作成している場合は、cancelOnFail
オプションを設定することでバリデーションチェーンを動的に停止できます。
<?php
use Phalcon\Validation;
use Phalcon\Validation\Message;
use Phalcon\Validation\Validator;
class MyValidator extends Validator
{
/**
* Executes the validation
*
* @param Phalcon\Validation $validator
* @param string $attribute
* @return boolean
*/
public function validate(Validation $validator, $attribute)
{
// If the attribute value is name we must stop the chain
if ($attribute === 'name') {
$validator->setOption('cancelOnFail', true);
}
// ...バリデーションの実行
}
}
空の値のバリデーションを避ける
空の値が渡された場合に検証が実行されないように、すべてのビルトインバリデータにオプションallowEmpty
を渡すことができます。
<?php
use Phalcon\Validation;
use Phalcon\Validation\Validator\Regex;
$validation = new Validation();
$validation->add(
'telephone',
new Regex(
[
'message' => 'The telephone is required',
'pattern' => '/\+44 [0-9]+/',
'allowEmpty' => true,
]
)
);
再起的バリデーション
afterValidation()
メソッドを使用して、別のインスタンス内でValidationインスタンスを実行することもできます。 この例では、CompanyValidation
インスタンスをバリデーションすると、PhoneValidation
インスタンスもチェックされます。
<?php
use Phalcon\Validation;
class CompanyValidation extends Validation
{
/**
* @var PhoneValidation
*/
protected $phoneValidation;
public function initialize()
{
$this->phoneValidation = new PhoneValidation();
}
public function afterValidation($data, $entity, $messages)
{
$phoneValidationMessages = $this->phoneValidation->validate(
$data['phone']
);
$messages->appendMessages(
$phoneValidationMessages
);
}
}