
バリデーションはお問い合わせフォームなどの作成に欠かせないものです。Cakephpではモデルテーブル内に、各フォームに合わせたバリデーションを記述していきます。元々Cakephpに用意されているバリデーションメソッドで要件を満たすことができればよいのですが、場合によっては独自のバリデートが必要になるケースも多々あると思います。
カスタムバリデートの実際に記述し、それをコールしてみましょう。
step
1CustomValidation.phpファイルを作成
場所は任意でよいのかも?ですが、とりあえずModel/Tableと密接するので、その配下にディレクトリとファイルを作成することにします。(少なくとも関連性がある場所がいい)
Model/Table/Validation という形でディレクトリを作成しましょう。
step
2CustomValidationを記述してく
カスタムバリデートメソッドを CutomValidation.php 内で記述します。継承元はValidationになります。
<?php
declare(strict_types=1);
namespace App\Model\Validation;
use Cake\Validation\Validation;
/**
* カスタムバリデーション
*/
class CustomValidation extends Validation
{
/**
* [独自validateルール関数] URLは正しいか?
*
* @param string $type 'pattern1' | 'pattern2'
* @return bool
*/
public static function validateCorrectUrl($data, $type, $context): bool
{
$params = self::getParamsFromUrl($data);
if (!$params) {
return false;
}
// 当該パターン以外ならfalse
if ($type != 'pattern1' || $type != 'pattern2') {
return false;
}
// 期待するパラメータが存在した場合はバリデート通過
return true;
}
/**
* urlからパラメータを抽出
*
* @param string $url URL
* @return array|false [期待するURLのパラメータ]
*/
private static function getParamsFromUrl($url)
{
// 正しいURLだった場合は各パラメータの値を返す
// 略
}
}
得にコードに意味はありません。(めんどくさいから最後略に...)
注意点としては、カスタムバリデート内の各メソッドにstaticが付与されていることです。
例えば、もし、staticにせず、validateCorrectUrl() メソッド内に $this->getParamsFromUrl() という形で呼び出したら、
Using $this when not in object context ~
という形でエラーになります。
Cakephpドキュメントを見てみると、
カスタムバリデートを利用する際、
// クラス名を使います。メソッドは静的なものでなければなりません。
$validator->setProvider('custom', 'App\Model\Validation');
https://book.cakephp.org/4/ja/core-libraries/validation.html#adding-validation-providers
という感じで、メソッドは静的なものであることが明記されています。
ドキュメントにしっかり目を通せば、エラーに遭遇することもないでしょうけども。まあ、注意ということで。
step
3テーブル内でカスタムバリデーションをsetProvider()で呼び出す
カスタムバリデートを利用するために、setProvider()で呼び出します。
/**
* entity生成時に作動するバリデーション
*
* @param \Cake\Validation\Validator $validator A Validator instance
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator): Validator
{
$validator->setProvider('customValidation', 'App\Model\Validation\CustomValidation');
$validator->add('correct_url', 'validateCorrectUrl', [
'rule' => 'validateCorrectUrl',
'provider' => 'customValidation',
'message' => '正しいURLではありません',
]);
}
ruleにカスタムプロバイダーメソッド、providerプロパティにsetProvider()で指定したプロバイダ名で呼び出すことができます。
カスタムバリデーションの定義の仕方と、その呼び出しについてはこれで大丈夫だと思います。
カスタムバリデーションに追加引数を渡したい場合
カスタムバリデーションメソッドに追加で引数を渡したい場合は、
shortcode
'rule' => ['validateCorrectUrl', 'pattern1'],
という感じで、ruleプロパティを配列にしつつ、渡したい値を渡すことができます。
と、同時にどうやってカスタムプロバイダ内で受け取るのか?というと、
public function validateCorrectUrl($data, $type, $context): bool
{
// $typeの第二引数で値を取得できる
var_dump($type); // 'pattern1'
}
上記の様に第二引数で受け取ることができます。
カスタムバリデーションを任意テーブル内で定義しつつ呼び出す場合
別にカスタムバリデーションを外だし(外部ファイルでまとめる)するほどでもなくね?という場合もあるかと思います。
そのような場合、
// DefaultValidationメソッド内
$validator
->allowEmptyDate('fieldName')
->add('fieldName', 'fromTodayOn', [
'rule' => [$this, 'fromTodayOn'],
'message' => '本日以降の日付を入力してください。',
]);
}
// fromTodyOn()はpublicで定義すること
public function fromTodayOn()
{
// 任意実装(検証)後、true or false
return true;
}
ruleプロパティの配列第一引数を$thisとして自身を指定しておき、第二引数で fromTodayOn()を指定することで、同テーブル内に定義されたカスタムバリデーションメソッドをコールすることができます。