Edited at

【PHP】年月日が配列で渡ってくるときのバリデーション

More than 1 year has passed since last update.


目的

入力フォームの都合で次のような配列の形で年月日のデータが渡される。

$date = [

'year' => 1990,
'month' => 1,
'day' => 1,
];

このときに


  • 所定の型・形式なのか

  • 妥当な日付なのか

を検証したい。

なお、外部からの入力内容をチェックする想定なので


  • 渡されるデータの型は保証されていない

  • 数値 (int) が入る箇所には、「数値 (int)」「数値 (int) として解釈できる文字列」の両方を許可する

とする。


コード

日付の妥当性検証には PHP 組み込みの checkdate() を使う。

/**

* @param mixed $value チェック対象のデータ
* @return bool 所定の形式に従った、妥当な日付の場合に true
*/

function isValidDateArray($value): bool
{
if (!is_array($value)) {
return false;
}

$expectedKeys = ['year', 'month', 'day'];
foreach ($expectedKeys as $key) {
// キーが存在しない、またはそのキーに対する値が整数でなければ false を返す
if (!isset($value[$key]) || (filter_var($value[$key], FILTER_VALIDATE_INT) === false)) {
return false;
}
}

return checkdate($value['month'], $value['day'], $value['year']);
}

filter_var() による整数の検証についてはこちらを参照。

用途に合わせて整数の検証ロジックは書き換えるとよい。


動作確認


  • PHP 7.1.18

以下の assertion が全て満たされていることを確認。


$dataSets = [
'正常系_数値で指定された場合にtrueを返すこと' => [
'expected' => true,
'value' => [
'year' => 1990,
'month' => 1,
'day' => 1,
],
],
'正常系_文字列で指定された場合にtrueを返すこと' => [
'expected' => true,
'value' => [
'year' => '1990',
'month' => '1',
'day' => '1',
],
],
'配列が渡されていない場合にfalseを返すこと' => [
'expected' => false,
'value' => 1,
],
'キーが足りていない場合にfalseを返すこと' => [
'expected' => false,
'value' => [
'year' => 1990,
'month' => 1,
],
],
'正常系_余分なキーが存在している場合でもtrueを返すこと' => [
// NOTE: 今回ではこの形は許容している、必要なら余分なキーの存在チェックを足す
'expected' => true,
'value' => [
'year' => 1990,
'month' => 1,
'day' => 1,
'foo' => 'bar'
],
],
'非整数が渡された場合にfalseを返すこと' => [
'expected' => false,
'value' => [
'year' => 'a',
'month' => 1,
'day' => 1,
],
],
'不正な日付が渡された場合にfalseを返すこと' => [
'expected' => false,
'value' => [
'year' => 1990,
'month' => 2,
'day' => 29,
],
],
'うるう年の2月29日が渡された場合にtrueを返すこと' => [
'expected' => true,
'value' => [
'year' => 1980,
'month' => 2,
'day' => 29,
],
],
];

foreach ($dataSets as $testCase => $dataSet) {
assert(isValidDateArray($dataSet['value']) === $dataSet['expected'], $testCase);
}