1. 導入
Webシステムにおいて、ユーザープロフィールやキャンペーンページなどで「生年月日から星座を判定する」機能は、UI/UXを向上させるための定番機能です。しかし、単純なif文の羅列で実装するとコードが肥大化し、保守性が低下します。今回はPHPのDateTimeクラスを活用し、拡張性と可読性の高い星座判定ロジックの実装方法を解説します。
2. 基礎知識
星座判定は、特定の「月と日」がどの期間に含まれるかを判定する処理です。ここで重要となるのが、日付データの取り扱いです。PHPでは文字列で日付を管理するよりも、標準のDateTimeクラスを使用するのが基本です。これにより、不正な日付のバリデーションや、フォーマット変換を安全に行うことができます。
3. 実装/解決策
実務レベルでは、入力データの形式を厳格に制御する必要があります。ユーザーからの入力は、意図しない書式(例:2023-13-45など)である可能性があるため、DateTime::createFromFormatを使用して、指定したフォーマットと一致するかを厳密にチェックすることが重要です。また、判定ロジックを関数化し、ロジックとデータを分離することで、将来的なメンテナンスを容易にします。
4. サンプルプログラム
/
function getZodiac(DateTime $date): ?string
{
// 月と日を整数として取得
$m = (int)$date->format(‘n’);
$d = (int)$date->format(‘j’);
// 星座の定義データ(開始月, 開始日, 終了月, 終了日)
$zodiacs = [
[‘牡羊座’, 3, 21, 4, 19],
[‘牡牛座’, 4, 20, 5, 20],
[‘双子座’, 5, 21, 6, 21],
[‘かに座’, 6, 22, 7, 22],
[‘獅子座’, 7, 23, 8, 22],
[‘乙女座’, 8, 23, 9, 22],
[‘天秤座’, 9, 23, 10, 23],
[‘蠍座’, 10, 24, 11, 22],
[‘射手座’, 11, 23, 12, 21],
[‘山羊座’, 12, 22, 1, 19],
[‘水瓶座’, 1, 20, 2, 18],
[‘魚座’, 2, 19, 3, 20]
];
foreach ($zodiacs as [$name, $sm, $sd, $em, $ed]) {
// 判定ロジック:開始月か終了月の境界をチェック
if (($m === $sm && $d >= $sd) || ($m === $em && $d <= $ed)) {
return $name;
}
}
return null;
}
// 利用例:厳密な形式で日付を作成
$input = '2023-08-20';
$date = DateTime::createFromFormat('Y-m-d', $input);
if ($date && $date->format(‘Y-m-d’) === $input) {
echo getZodiac($date); // 出力: 獅子座
} else {
echo ‘無効な日付です’;
}
?>
5. 応用・注意点
実務でこのコードを導入する際は、以下の点に注意してください。
バリデーションの徹底:
DateTime::createFromFormat は、存在しない日付(例: 2月30日)を自動的に翌月に繰り越して生成する場合があります。これを防ぐには、生成後に元の入力値とフォーマット後の値を比較し、完全に一致するかを確認するロジック(サンプルコード内のif文)が必須です。
データの外部化:
もしアプリケーション内で多言語対応(英語や他の言語での星座名)が必要な場合は、星座の配列を定数や設定ファイルとして外出ししておくことで、ロジックを変更せずに表示内容を切り替えることができます。
型安全性の確保:
PHP 7.4以降では、関数の引数や戻り値に型宣言をすることで、予期せぬ型エラーを未然に防ぐことができます。実務コードでは、可能な限り厳密な型定義を行うことを推奨します。