ユーザ登録をする際に、18歳未満の人は登録できないようにしたかったのですが、 バリデーションの順番でエラーになってしまった。
元のコード
src/Model/Table/UsersTable.php
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
use Cake\Database\Schema\TableSchema;
use DateTime;
class ProfilesTable extends Table
{
public function validationDefault(Validator $validator)
{
$validator
->date('birthday')
->requirePresence('birthday', 'create')
->notEmpty('birthday', '生年月日を入力してください')
->add('birthday', [
'date' => [
'rule' => function ($value, $context) {
return (bool) preg_match('/^([1-9][0-9]{3})\/(0[1-9]{1}|1[0-2]{1})\/(0[1-9]{1}|[1-2]{1}[0-9]{1}|3[0-1]{1})$/', $value);
},
'message' => '生年月日はYYYY/MM/DDの形式で入力してください'
],
])
->add('birthday', [
'date' => [
'rule' => function($value, $context){
$birthdate = new DateTime($value);
$today = new DateTime();
$interval = $today->diff($birthdate);
return (bool) ($interval->y > 18);
},
'message' => '18歳未満の方は登録できません',
],
]);
YYYY/MM/DDの形式かどうかと18歳以上かどうか確認したい。
この時、**1984/11/**のような入力をするとエラーになってしまう。
DateTime::__construct(): Failed to parse time string (1984/11/) at position 4 (/): Unexpected character
18歳未満かどうか調べる時にもYYYY/MM/DDの形式かどうか調べてもいいのですが、それだとYYYY/MM/DDの形式でないときにエラー文が18歳未満の方は登録できませんになってしまうので、あまり良くない。
調べた結果、下から順番にバリデーションが行われていたので順番を変えてみた。
修正コード(順番を変えた)
src/Model/Table/UsersTable.php
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
use Cake\Database\Schema\TableSchema;
use DateTime;
class ProfilesTable extends Table
{
public function validationDefault(Validator $validator)
{
$validator
->date('birthday')
->requirePresence('birthday', 'create')
->notEmpty('birthday', '生年月日を入力してください')
->add('birthday', [
'date' => [
'rule' => function($value, $context){
$birthdate = new DateTime($value);
$today = new DateTime();
$interval = $today->diff($birthdate);
return (bool) ($interval->y > 18);
},
'message' => '18歳未満の方は登録できません',
],
])
->add('birthday', [
'date' => [
'rule' => function ($value, $context) {
return (bool) preg_match('/^([1-9][0-9]{3})\/(0[1-9]{1}|1[0-2]{1})\/(0[1-9]{1}|[1-2]{1}[0-9]{1}|3[0-1]{1})$/', $value);
},
'message' => '生年月日はYYYY/MM/DDの形式で入力してください'
],
]);
とりあえず、エラーにはならなくなった。
JUST HACK IT!