DateTime クラス(オブジェクト)は良く使うクラスですが、コピーについては注意が必要なことがあります。
以下のソースを見て下さい。単に「$datetime1」に日付を設定し「$datetime2」にコピーをしています。
<?php $datetime1 = new DateTime('2022-11-20 10:30:00'); $datetime2 = $datetime1; $datetime2->modify('+1 day'); echo "\$datetime1 = ".$datetime1->format('Y-m-d')."<br>\n"; echo "\$datetime2 = ".$datetime2->format('Y-m-d')."<br>\n"; ?>
これを実行するとブラウザに以下の様に表示されます。
$datetime1 = 2022-11-21 $datetime2 = 2022-11-21
「$datetime2」にコピーをしているので「$datetime1」に影響しないと思いきや、「$datetime2」に modify メソッドで日付を1日加算すると 「$datetime1」「$datetime2」共に同じ日付になります。
「$datetime2」へのコピーでは参照渡しの様な感じになる様です。(実際のPHPの中では参照では無い様ですが…)
そこで、これを解消するにはクローン命令で別のインスタンスを作成し「$datetime2」に代入する必要があります。
<?php $datetime1 = new DateTime('2022-11-20 10:30:00'); $datetime2 = clone $datetime1; echo "\$datetime1 = ".$datetime1->format('Y-m-d')."<br>\n"; echo "\$datetime2 = ".$datetime2->format('Y-m-d')."<br>\n"; $datetime2->modify('+1 day'); echo "\$datetime2 = ".$datetime2->format('Y-m-d')."<br>\n"; ?>
これを実行するとブラウザに以下の様に表示されます。
$datetime1 = 2022-11-20 $datetime2 = 2022-11-20 $datetime2 = 2022-11-21
modify や add メソッドの戻り値は自分自身の DateTime オブジェクトを返します。
実際 PHP の正規のマニアルには以下の様に記述されています。
戻り値: メソッドチェインに使う、変更された DateTime オブジェクトを返します。
メソッドチェイン とは以下の様な使い方です。
<?php $datetime1 = new DateTime('2022-11-30 10:30:00'); echo "\$datetime1 = ".$datetime1->modify('+1 day')->format('Y-m-d')."<br>\n"; echo "\$datetime1 = ".$datetime1->modify('+1 day')->modify('+1 day')->format('Y-m-d')."<br>\n"; echo "\$datetime1 = ".$datetime1->format('Y-m-d')."
\n"; ?>
3行目では modify メソッドの直後に format メソッドを呼出しています。modify は DateTime オブジェクトを返すので、この方法が可能です。 さらに、4行目では modify メソッドの直後に再度 modify メソッドを呼出しています。
実行結果は以下の様に表示されます。 5行目では再度「$datetime1」の値を表示していますが、3回の modify の実行で日付は初期値から3日後になります。 modify では自分のオブジェクトを変更することがわかります。
$datetime1 = 2022-12-01 $datetime1 = 2022-12-03 $datetime1 = 2022-12-03
ところで DateTime の値を変更する modify メソッド等で新しい DateTime オブジェクトを返したい場合には DateTimeImmutable クラスを使用します。Immutable(イミュータブル) とは「不変」「変わらない」ことを意味するそうです。
では DateTimeImmutable クラスを使用して最初のソースを変更します。
<?php $datetime1 = new DateTimeImmutable('2022-11-20 10:30:00'); $datetime2 = $datetime1->modify('+1 day');; echo "\$datetime1 = ".$datetime1->format('Y-m-d')."<br>\n"; echo "\$datetime2 = ".$datetime2->format('Y-m-d')."<br>\n"; ?>
実行結果は以下の様に表示されます。 「$datetime1」の modify メソッドの結果は別のオブジェクトとして「$datetime2」に設定された様です。 ただし、「$datetime1」の値は変化がありません。
$datetime1 = 2022-11-20 $datetime2 = 2022-11-21
コメント