【PHP8.x】DatePeriod::__construct()メソッドの使い方
__constructメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『__constructメソッドは、新しいDatePeriodオブジェクトを生成し初期化するメソッドです。このメソッドは、new DatePeriod()構文でオブジェクトが作成される際に自動的に呼び出される、コンストラクタと呼ばれる特別なメソッドです。主な役割は、指定された期間における、一定間隔の日時の繰り返しを表現するオブジェクトを作成することです。最も一般的な使い方では、第一引数に期間の開始日時をDateTimeInterfaceオブジェクトで、第二引数に繰り返しの間隔をDateIntervalオブジェクトで、第三引数に期間の終了日時をDateTimeInterfaceオブジェクトで指定します。これにより、「2023年4月1日から1週間ごと、同月末まで」といった日付のシーケンスを簡単に定義できます。また、終了日時の代わりに繰り返しの回数を整数で指定することも可能です。さらに、ISO 8601形式の繰り返し期間を表す文字列を一つ渡すことでもオブジェクトを生成できます。このメソッドによって初期化されたDatePeriodオブジェクトは、foreachループと組み合わせて使うことで、期間内の各日時を順番に処理するのに役立ちます。
構文(syntax)
1new DatePeriod($start, $interval, $end, $options = 0);
引数(parameters)
string|DateTimeInterface $start, ?DateInterval $interval = null, DateTimeInterface|int|null $end = null, int $options = 0
- DateTimeInterface|string $start: 期間の開始日時を指定します。DateTimeInterfaceオブジェクトまたはISO 8601形式の文字列で指定できます。
- ?DateInterval $interval = null: 期間の間隔を指定します。DateIntervalオブジェクトで指定します。省略した場合は、デフォルトで1日となります。
- DateTimeInterface|int|null $end = null: 期間の終了日時を指定します。DateTimeInterfaceオブジェクト、UNIXタイムスタンプ(整数)、またはnullで指定できます。nullの場合は、終了日時が指定されません。
- int $options = 0: 期間のオプションを指定します。DatePeriod::EXCLUDE_START_DATEなどの定数で指定します。
戻り値(return)
戻り値なし
戻り値はありません
サンプルコード
PHP 8コンストラクタプロパティで日付期間を生成する
1<?php 2 3/** 4 * DatePeriodクラスを模倣し、特定期間の日付を生成するクラス 5 */ 6final class CustomDatePeriod 7{ 8 /** 9 * PHP 8.0のコンストラクタプロパティプロモーションを使用。 10 * 引数でプロパティを宣言し、同時に初期化します。 11 * 12 * @param public readonly DateTimeInterface $start 開始日時 13 * @param public readonly DateInterval $interval 間隔 14 * @param public readonly DateTimeInterface $end 終了日時 15 */ 16 public function __construct( 17 public readonly DateTimeInterface $start, 18 public readonly DateInterval $interval, 19 public readonly DateTimeInterface $end, 20 ) { 21 } 22 23 /** 24 * 期間内の日付を配列として取得します。 25 * 26 * @return DateTimeInterface[] 27 */ 28 public function getDates(): array 29 { 30 $dates = []; 31 $current = clone $this->start; 32 33 while ($current <= $this->end) { 34 $dates[] = clone $current; 35 $current->add($this->interval); 36 } 37 38 return $dates; 39 } 40} 41 42// 2023年1月1日から2023年1月7日まで、1日間隔で日付を生成 43$start = new DateTime('2023-01-01'); 44$interval = new DateInterval('P1D'); // P1Dは1日の間隔を示す 45$end = new DateTime('2023-01-07'); 46 47// コンストラクタプロパティプロモーションにより、引数が直接プロパティに代入される 48$period = new CustomDatePeriod($start, $interval, $end); 49 50// 結果を出力 51echo "期間: " . $period->start->format('Y-m-d') . " から " . $period->end->format('Y-m-d') . PHP_EOL; 52echo "間隔: 1日ごと" . PHP_EOL; 53echo "--------------------" . PHP_EOL; 54 55foreach ($period->getDates() as $date) { 56 echo $date->format('Y-m-d') . PHP_EOL; 57}
このサンプルコードは、指定した期間と間隔に基づいて一連の日付を生成するCustomDatePeriodクラスの実装例です。これはPHPの組み込みクラスであるDatePeriodの動作を模倣したものです。
このコードの最大の特徴は、PHP 8.0から導入された「コンストラクタプロパティプロモーション」という機能を利用している点です。クラスのコンストラクタ__constructの引数定義にpublic readonlyというキーワードが付与されています。これにより、引数で渡された値を初期値として持つ同名のプロパティが自動的に宣言・初期化されます。従来はクラスの先頭でプロパティを宣言し、コンストラクタ内で$this->start = $start;のように代入する必要がありましたが、この機能によってコードをより簡潔に記述できます。
コードの実行部分では、開始日、1日の間隔、終了日をそれぞれDateTimeオブジェクトとDateIntervalオブジェクトとして作成し、CustomDatePeriodクラスのインスタンスを生成しています。コンストラクタプロパティプロモーションにより、$period->startのようにインスタンスのプロパティへ直接アクセスが可能です。最後にgetDatesメソッドを呼び出し、生成された日付オブジェクトの配列をループ処理で一つずつ画面に出力しています。
このサンプルコードは、PHP 8.0からの新機能「コンストラクタプロパティプロモーション」を使い、引数でプロパティの宣言と初期化を同時に行っています。readonlyキーワードはPHP 8.1からの機能で、一度初期化したプロパティへの再代入を防ぎます。ただし、DateTimeオブジェクト自体は変更可能なため、readonlyであっても$period->start->modify('+1 day');のように内部状態を変更できてしまいます。これを防ぎ、より安全なコードにするには、変更不可能なDateTimeImmutableクラスの使用を推奨します。また、getDatesメソッド内でcloneを使用している点も重要です。これを使わないと、ループ処理の中で元の開始日時オブジェクトの値まで変更されてしまうため、オブジェクトの複製を作成しています。
PHP DatePeriod継承とparent::__construct()
1<?php 2 3/** 4 * CustomDatePeriodクラスは、DatePeriodクラスを継承しています。 5 * この例では、子クラスのコンストラクタがどのように親クラス(DatePeriod)のコンストラクタを 6 * 呼び出すか(`parent::__construct()`)を示しています。 7 */ 8class CustomDatePeriod extends DatePeriod 9{ 10 private string $purpose; 11 12 /** 13 * CustomDatePeriodクラスのコンストラクタ。 14 * 15 * このコンストラクタは、親クラスであるDatePeriodのコンストラクタを呼び出して、 16 * 日付期間の基本的な初期化を行います。同時に、このクラス独自のプロパティも設定します。 17 * 18 * @param string|DateTimeInterface $start 期間の開始日時 19 * @param DateInterval $interval 期間の間隔 20 * @param DateTimeInterface|int|null $end 期間の終了日時 21 * @param int $options DatePeriodオプション (例: DatePeriod::EXCLUDE_START_DATE) 22 * @param string $purpose この期間の目的 23 */ 24 public function __construct( 25 string|DateTimeInterface $start, 26 DateInterval $interval, 27 DateTimeInterface|int|null $end = null, 28 int $options = 0, 29 string $purpose = '一般的な期間' 30 ) { 31 // 親クラス(DatePeriod)のコンストラクタを呼び出し、 32 // DatePeriodオブジェクトの基本的な機能を初期化します。 33 // これにより、開始日時、間隔、終了日時が設定され、日付の反復処理が可能になります。 34 parent::__construct($start, $interval, $end, $options); 35 36 // この子クラス独自のプロパティを初期化します。 37 $this->purpose = $purpose; 38 } 39 40 /** 41 * この期間の目的を取得します。 42 * 43 * @return string 期間の目的 44 */ 45 public function getPurpose(): string 46 { 47 return $this->purpose; 48 } 49} 50 51/** 52 * CustomDatePeriodクラスの利用例。 53 * コンストラクタの動作と、parent::__construct()の役割を示します。 54 */ 55function demonstrateCustomDatePeriodUsage(): void 56{ 57 echo "--- CustomDatePeriodのインスタンス生成と利用 ---\n"; 58 59 // CustomDatePeriodのインスタンスを生成。 60 // コンストラクタに引数を渡し、親クラスのDatePeriodとこのクラス独自のプロパティを初期化します。 61 $customPeriod = new CustomDatePeriod( 62 new DateTime('2024-03-01'), // 開始日時 63 new DateInterval('P7D'), // 1週間ごと 64 new DateTime('2024-04-01'), // 終了日時 65 DatePeriod::EXCLUDE_START_DATE, // オプション: 開始日を含まない 66 '月次レポート作成のための週次集計期間' // この期間の目的 67 ); 68 69 echo "期間の目的: " . $customPeriod->getPurpose() . "\n"; 70 echo "この期間に含まれる日付:\n"; 71 72 // CustomDatePeriodはDatePeriodを継承しているので、foreachで反復処理が可能です。 73 foreach ($customPeriod as $date) { 74 /** @var DateTimeImmutable $date 日付オブジェクトはDateTimeImmutableになります */ 75 echo "- " . $date->format('Y-m-d') . "\n"; 76 } 77 78 echo "\n(注意: DatePeriod::EXCLUDE_START_DATE オプションにより、開始日 '2024-03-01' は含まれていません。)\n"; 79} 80 81// サンプルコードの実行 82demonstrateCustomDatePeriodUsage();
このサンプルコードは、PHPのクラス継承において、子クラスが親クラスのコンストラクタを呼び出す方法を解説するものです。
DatePeriodクラスの__constructメソッドは、開始日時、繰り返し間隔、終了日時などを引数として受け取り、一連の日付を繰り返し処理するためのオブジェクトを初期化します。このメソッドはコンストラクタのため、戻り値はありません。
このコードでは、DatePeriodを継承したCustomDatePeriodという子クラスを定義しています。この子クラスは、日付期間の情報に加えて「目的(purpose)」という独自のプロパティを持ちます。
子クラスのコンストラクタでは、まずparent::__construct()を呼び出しています。これは、親クラスであるDatePeriodのコンストラクタを呼び出し、日付期間に関する基本的な初期化処理を任せるための構文です。親クラスの初期化が終わった後に、子クラス独自のプロパティである$purposeに値を設定しています。
このようにparent::__construct()を使うことで、親クラスの機能を再利用しつつ、子クラスに新たな機能やプロパティを安全に追加・拡張することができます。
子クラスでコンストラクタを定義する際、親クラスのコンストラクタは自動で実行されません。そのため、親クラスが持つ機能を正しく動作させるには、parent::__construct()を明示的に呼び出す必要があります。この呼び出しを忘れると、親クラスの初期化が行われず、オブジェクトが不完全な状態になり、予期せぬエラーの原因となります。サンプルコードでは、この記述によってDatePeriodクラスの持つ日付の反復処理などの基本的な機能を確実に引き継いでいます。子クラスのコンストラクタは、親が必要とする引数を受け取って渡し、同時に独自のプロパティを追加で初期化する、という重要な役割を担っています。