CarbonオブジェクトはMutable(変更可能)という特性を持っています。
Mutableは便利である反面、注意しなければならない点もあるため、自分用のメモも兼ねて記事を書いてみました。
Carbonとは?
日付と時刻を簡単に操作できるライブラリです。DateTimeクラスを拡張しており色々と便利なメソッドが利用できます。
Mutableとは?
Mutableとは、オブジェクトの状態が変更可能であるということです。
例えば以下コードのように$date1
に対して2023年4月1日という日付のcarbonインスタンスを代入し、
addDaysメソッドを使って、そこから7日後の日付(4月8日)を$date2
に代入したとします。
$date1 = Carbon::createFromDate(2023, 4, 1);
$date2 = $date1->addDays(7);
この状態で、diffInDaysメソッドを使って$date1
と$date2
の差が何日なのかを確認してみます。
当然7日になるだろうと思いますが、、
dd($date1->diffInDays($date2));
// 出力結果「0」
なんと「0」日になってしまいました。
なぜこんなことが起きるのでしょうか?
それは、以下の行で$date1
自体も4月1日から4月8日に変更になっているからです。
$date2 = $date1->addDays(7);
つまり、$data1 = ~~
といった形で代入をしなくても
$date1->addDays(7);
とするだけで状態を変更できるということです。
$date1 = Carbon::createFromDate(2023, 4, 1);
$date1->addDays(7);
dd($date1->format('Y-m-d'));
// 出力結果「2023-4-8」
これがMutable(変更可能)なオブジェクトの特性です。
便利な側面もありますが、気付かずに意図しない変更が行われてしまう可能性もあります。
意図しない変更を避ける方法
方法①:copy()を使う
以下のように、$date1
に対してcopyメソッドを使って複製を作ったあとにaddDaysメソッドを使用すれば$date1
は4月1日のままです。
$date1 = Carbon::createFromDate(2023, 4, 1);
$date2 = $date1->copy()->addDays(7);
dd($date1->format('Y-m-d'));
// 出力結果「2023-4-1」
方法②:CarbonImmutableを使う
以下のように、Carbon
クラスではなくCarbonImmutable
クラスを使用するとMutable(変更可能)ではないインスタンスが作成されるので、意図しない変更を避けることができます。
$date1 = CarbonImmutable::createFromDate(2023, 4, 1);
$date2 = $date1->addDays(7);
dd($date1->format('Y-m-d'));
// 出力結果「2023-4-1」
なお、MutableとImmutableは、以下のようにtoImmutableメソッドやtoMutableメソッドを使用して相互変換が可能です。
$date1 = Carbon::now();
$date1->toImmutable();
// Immutableに変換
$date2 = CarbonImmutable::now();
$date2->toMutable();
// Mutableに変換