【PHP】Carbonで学ぶミュータブルとイミュータブル

# Carbonとは

<br>

PHPの日付操作で使われるライブラリ。
Laravelに標準で入っている。

https://github.com/briannesbitt/carbon

***

# ミュータブル・イミュータブルとは

<br>

ミュータブル
→ **可変**

イミュータブル
→ **不変**

***

## ミュータブルの例（Carbon）

```php
$date = new \Carbon\Carbon('2018-01-01');
$nextYear = $date->addYear(); // 1年加算する

echo $nextYear->format('Y-m-d');
// -> ???
```

***

## ミュータブルの例（Carbon）

```php
$date = new \Carbon\Carbon('2018-01-01');
$nextYear = $date->addYear(); // 1年加算する

echo $nextYear->format('Y-m-d');
// -> ???
```

→ 2019-01-01

***

## ミュータブルの例（Carbon）

```php
$date = new \Carbon\Carbon('2018-01-01');
$nextYear = $date->addYear();

echo $nextYear->format('Y-m-d');
// -> 2019-01-01

echo $date->format('Y-m-d');
// -> ???
```
***

## ミュータブルの例（Carbon）

```php
$date = new \Carbon\Carbon('2018-01-01');
$nextYear = $date->addYear();

echo $nextYear->format('Y-m-d');
// -> 2019-01-01

echo $date->format('Y-m-d');
// -> ???
```

→ 2019-01-01

:::note info
`addYear()`メソッドが`$date`自体を変更している！
:::

***

## イミュータブルの例（CarbonImmutable）

```php
$date = new \Carbon\CarbonImmutable('2018-01-01');
$nextYear = $date->addYear();

echo $nextYear->format('Y-m-d');
// -> ???
```

***

## イミュータブルの例（CarbonImmutable）

```php
$date = new \Carbon\CarbonImmutable('2018-01-01');
$nextYear = $date->addYear();

echo $nextYear->format('Y-m-d');
// -> ???
```

→ 2019-01-01

***

## イミュータブルの例（CarbonImmutable）

```php
$date = new \Carbon\CarbonImmutable('2018-01-01');
$nextYear = $date->addYear();

echo $nextYear->format('Y-m-d');
// -> 2019-01-01

echo $date->format('Y-m-d');
// -> ???
```

***

## イミュータブルの例（CarbonImmutable）

```php
$date = new \Carbon\CarbonImmutable('2018-01-01');
$nextYear = $date->addYear();

echo $nextYear->format('Y-m-d');
// -> 2019-01-01

echo $date->format('Y-m-d');
// -> ???
```

→ 2018-01-01

:::note info
`addYear()`メソッドが`$date`自体を変更していない！
:::

***

## ミュータブルとイミュータブルの違い

```php
$date = new \Carbon\Carbon('2018-01-01');
$date->addYear();

echo $date->format('Y-m-d'); // -> 2019-01-01 
// 元のオブジェクトが変更されてしまっている😱

$date = new \Carbon\CarbonImmutable('2018-01-01');
$date->addYear();

echo $date->format('Y-m-d'); // -> 2018-01-01 
// 元のオブジェクトが変更されていない！
```

***

## ここまでのまとめ

<br>

- ミュータブルな操作とは**元のオブジェクトの変更を伴う操作**である。
- ミュータブルな操作は**破壊的**とも呼ばれることがある。
- ミュータブルな操作は**想定しない挙動**を起こすことがあるため、安全性が低いとされている。

<br>
→　　「ミュータブル」とか「破壊的メソッド」とか調べると色々な記事が出てきます。

***

# 問題

***

## 第一問

ミュータブルな操作

```php
$date = new \Carbon\Carbon('2018-01-01');
$nextYear = $date; // 代入する
$nextYear->addYear();

echo $nextYear->format('Y-m-d');
// -> 2019-01-01
echo $date->format('Y-m-d');
// -> ???
```

***

## 第一問

ミュータブルな操作

```php
$date = new \Carbon\Carbon('2018-01-01');
$nextYear = $date; // 代入する
$nextYear->addYear();

echo $nextYear->format('Y-m-d');
// -> 2019-01-01
echo $date->format('Y-m-d');
// -> ???
```

→ 2019-01-01

:::note warn
ただ代入するだけでは[参照渡し](https://www.php.net/manual/ja/language.oop5.references.php)になってしまう！
:::

***

## 第二問

Carbonのままイミュータブルに操作するには？

```php
$date = new \Carbon\Carbon('2018-01-01');
$nextYear = $date;
$nextYear->addYear();

echo $nextYear->format('Y-m-d'); // -> 2018-01-01 
echo $date->format('Y-m-d'); // -> 「2018-01-01」と表示されるようにしたい！
```

***

## 第二問

Carbonのままイミュータブルに操作するには？

```diff_php
$date = new \Carbon\Carbon('2018-01-01');
- $nextYear = $date;
+ $nextYear = clone $date;
$nextYear->addYear();

echo $nextYear->format('Y-m-d'); // -> 2018-01-01 
echo $date->format('Y-m-d'); // -> 2018-01-01 
```

→ `clone`を使おう！

***

# cloneとは

→ 親オブジェクトをコピーする際に、そのコピーが独立したオブジェクトの コピーを有するように、そのオブジェクトのインスタンスを新たに作成したい場合

https://www.php.net/manual/ja/language.oop5.cloning.php

***

# ご清聴ありがとうございました。