目的
入力フォームの都合で次のような配列の形で年月日のデータが渡される。
$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);
}