🔥
CodeIgniter4 バリデーションルール valid_date は年月の検証に使用できるのか
はじめに
Validation — CodeIgniter 4.2.10 documentation
Rule: valid_date
Description: Fails if field does not contain a valid date. Accepts an optional parameter to matches a date format.
Example: valid_date[d/m/Y]
valid_date[Y/m]
のように指定した場合に期待する結果が得られなかった為、実装を確認した。
実行環境
- CodeIgniter 4.2.10
動作確認
system\Validation\FormatRules.php
<?php
//...
class FormatRules
{
//...
public function valid_date(?string $str = null, ?string $format = null): bool
{
if ($str === null) {
return false;
}
if (empty($format)) {
return strtotime($str) !== false;
}
$date = DateTime::createFromFormat($format, $str);
$errors = DateTime::getLastErrors();
if ($date === false) {
return false;
}
// PHP 8.2 or later.
if ($errors === false) {
return true;
}
return $errors['warning_count'] === 0 && $errors['error_count'] === 0;
}
}
DateTime::createFromFormat
のパース結果で判定されていることがわかる。
正常系
var_dump(DateTime::createFromFormat('Y/m', '2022/11'));
object(DateTime)#1 (3) {
["date"]=>
string(26) "2022-11-15 12:30:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(10) "Asia/Tokyo"
}
異常系
var_dump(DateTime::createFromFormat('Y/m', '2022'));
bool(false)
存在しない月
var_dump(DateTime::createFromFormat('Y/m', '2022/18'));
object(DateTime)#1 (3) {
["date"]=>
string(26) "2023-06-15 12:30:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(10) "Asia/Tokyo"
}
オブジェクトが返却される為、valid_date
は正常と判断する。
代案
年月の妥当性をチェックする適当なカスタムバリデーションを実装する。
app\Config\Validation.php
public $ruleSets = [
Rules::class,
FormatRules::class,
FileRules::class,
CreditCardRules::class,
+ CustomRules::class,
];
app\Config\CustomRules.php
<?php
namespace Config;
class CustomRules
{
public function valid_ym(?string $str = null): bool
{
return (bool)preg_match('/^(19|20)\d{2}\/(0[1-9]|1[0-2])$/', $str);
}
}
app\Language\ja\Validation.php
<?php
return [
'valid_ym' => '{field} には、有効な年月を入力してください。',
];
Discussion
確かに、月がオーバーフローしても、DateTimeが警告も出さないですね。
日付だと警告が出ますが。
コメントありがとうございます。
そうですね、年月日まで正確に指定している場合は問題ありませんでした。