LoginSignup
78
17

More than 1 year has passed since last update.

2歳息子「パパ,PHP の Carbon はミュータブルだよ?」

Last updated at Posted at 2022-06-11

リモートワーク中のある日

ワイ「(カタカタカタカタ・・・ッターン!)」

息子(2歳)「パパ,お仕事捗ってそうだね!」

ワイ「仕事?ちゃうで.これは自分専用のダイエット管理ツールや!」
ワイ「リモートワークやと,仕事せんでもバレへんからなぁ」
ワイ「Slack だけ即レスしとけば,仕事できる男に見えんねん」
ワイ「その他の時間は個人開発や!」

息子「パパ最近リモートワークで外に全く出ないから,お腹周りがぷにぷにだもんね」
息子「ダイエット管理で体重が減っても,仕事もしてないからお給料も減っちゃうよ?」

ワイ「弊社は給与自己決定やから,仕事せんでも給料はもらえるねん」

社長「(お前 Discord ミュートにし忘れてて全部聞こえとるからな...!)」

新しい機能を追加したい

ワイ「よしよし,新しい機能でも追加するか!」
ワイ「1ヶ月前の自分の体重と,今日の体重とで」
ワイ「どれだけ差があるかを計算する機能を作るで」
ワイ「体重が1kg以上減っていたら,アプリ内通貨の”痩せコイン”がもらえる仕組みや...!」
ワイ「今流行の ダイエット2Earn や!」

ワイ「まずは,今日の日付を取得するところからやな」
ワイ「日付操作には,Carbon というライブラリが便利らしいから,使ってみよか」
ワイ「なになに, Laravel にはもともと Carbon は入っとるから」
ワイ「わざわざインストールしなくてええんか」
ワイ「Laravel はさすが便利やな〜」

ワイ「まずは Carbon を import して...」

use Carbon\Carbon;

ワイ「今日の日付を取得してみるで」

$today = Carbon::today('Asia/Tokyo');
// 2022-06-01 00:00:00

ワイ「おぉ〜,簡単やな」
ワイ「そして,1ヶ月前の日付も取得せなあかんな」
ワイ「なになに,Carbon は日付の足し引きも簡単にできるんやな」
ワイ「1ヶ月引くには, subMonth() を使えば良さそうやな」

$oneMonthAgo = $today->subMonth();
// 2022-05-01 00:00:00

ワイ「できたできた」
ワイ「あとは,それぞれの体重をデータベースから取得して」
ワイ「引き算するだけやな!」

// 今日の体重を取得する
$todayWeight = BodyWeight::query()
    ->where('measurement_date', $today)
    ->first();

// 1ヶ月前の体重を取得する
$oneMonthAgoWeight = BodyWeight::query()
    ->where('measurement_date', $oneMonthAgo)
    ->first();

// 1ヶ月前の体重から今日の体重を引く
$diffWeight = $oneMonthAgoWeight->value - $todayWeight->value;

return $diffWeight >= 1
  ? 'よく頑張ったな!1痩せコイン!' // 1kg以上体重が減っていた場合
  : 'もっと努力しろ!デブが!' // 1kgも体重が減っていない場合

新機能完成!のはずが...

ワイ「よし!できたで!!」
ワイ「サイトにアクセスしてみてみよか」

ダイエットツール君「もっと努力しろ!デブが!」

ワイ「そんな言い方しなくても...」
ワイ「ワイだって努力してんねん...」
ワイ「1日に食べるアイスの量,5個から4個に減らしたねん!!」

息子「(自分が設定した文言でしょ...)」
息子「(っていうかアイス食べすぎでしょ...)」
息子「(僕には全然くれないくせに...)」

ワイ「あれ?」
ワイ「記録をみると,今日の体重は57kgで」
ワイ「先月は58kgやから」
ワイ「褒めてもらえるはずなんやけど...?」

息子先生登場

息子「パパ,ちょっとコード見せて!」

ワイ「おお,息子くん」
ワイ「PHP のコード読めるん?」
ワイ「そういえばこの間,牛さんの絵本とか言って,」
ワイ「オライリー社のC実践プログラミング1をパパの本棚から引っ張り出しとったからな」

息子「あ〜,パパ, PHP の Carbon はミュータブルだよ?」

ワイ「ミュウダブる!?」
ワイ「幻のポケモンは世界に1体しかおらんのやで!」
ワイ「そんなんできるの,もう セレクトバグ2 やないか...」

息子「パパ,令和ベイビーに向かっていつの時代の話をしてるの?」
息子「”ミュウダブる” じゃなくて ”ミュータブル”!」
息子「可変ってこと!」

ワイ「可変...?変数なんていつでも上書きできてまうやん」
ワイ「てか自分で自分のこと令和ベイビーって言うなや」

息子「そういう話じゃなくてね」
息子「ミュータブルは,オブジェクトが作成されたあとも状態を変えることができるって意味なの」
息子「その反対がイミュータブルで,一度作られたら状態は変えられないの」
息子「そしてね」
息子「Carbon の日付操作系のメソッドは,自分自身,つまり $this を返すの」

ワイ「$this を返す...?」

息子「そう. だから, パパが使った subMonth() は,自分自身の日付を1ヶ月分引くから」
息子「実は $today$oneMonthAgo同じインスタンスなの」
息子「実験してみる?」

息子「まずは,さっきみたいに現在の日付を取得して」
息子「返ってきた Carbon インスタンスのオブジェクト ID を見てみよう」

ワイ「オブジェクトの ID とか見れるん?」

息子「PHP ビルトインの spl_object_id() を使えば見れるよ!」

$today = Carbon::today('Asia/Tokyo');
// 2022-06-01 00:00:00

$todayId = spl_object_id($today);
// 3502

ワイ「お,このインスタンスの ID は 3502 ってことやな!」

息子「そうだね」
息子「じゃぁ,この $today から1ヶ月引いて,またオブジェクト ID を見てみるね」

$oneMonthAgo = $today->subMonth();
// 2022-05-01 00:00:00

$oneMonthAgoId = spl_object_id($oneMonthAgo);
// 3502

ワイ「ほんまや...!」
ワイ「同じインスタンスが返ってきてるやんけ!」
ワイ「知らんかったわ...」
ワイ「でも,それじゃぁどうしたらええんや?」
ワイ「こんな風に...」

$today = Carbon::today();
$oneMonthAgo = Carbon::today()->subMonth();

ワイ「2回 Carbon インスタンスを作ったらええんか?」

息子「それでもいいけど...」
息子「他にもいくつか方法があるよ!」
息子「例えば」

$today = Carbon::today('Asia/Tokyo');
$oneMonthAgo = $today->copy()->subMonth();

息子「こうやってかけば」
息子「copy()$today に入っている Carbon インスタンスの clone を作ってくれるから」
息子「subMonth()$today とは別のインスタンスに対して実行されるよ」

ワイ「おお!これは便利やな!」
ワイ「直感的やし,分かりやすいな!」

息子「他にも...」

$today = Carbon::today('Asia/Tokyo');
$oneMonthAgo = $today->toImmutable()->subMonth();

息子「こうすれば, copy() を使ったときと同じで, $today とは別インスタンスが返ってくる」
息子「しかも,これはイミュータブルにして返してくれるから」
息子「$oneMonthAgo は不変なインスタンスになるの」

ワイ「イミュータブルにできるん!?」
ワイ「そっちの方が混乱が無くてええやんけ!」
ワイ「でも,それなら $today からイミュータブルにしたいなぁ」
ワイ「あっ」

$today = Carbon::today('Asia/Tokyo')->toImmutable();
$oneMonthAgo = $today->subMonth();

ワイ「こうしたらええやんけ!」
ワイ「ワイ,天才やなぁ」

息子「パパ,残念!」
息子「全然天才じゃない!」

ワイ「ファッ!?」
ワイ「なんでそんなこと言うねん!」
ワイ「天才的な思いつきやろ!?」

息子「CarbonImmutable っていう, Carbon のイミュータブルバージョンがあるよ」

ワイ「ファッ!?!?」
ワイ「そんなものが...」

息子「使い方は Carbon と同じで」

$today = CarbonImmutable::today('Asia/Tokyo');
$todayId = spl_object_id($today);
// 3503

$oneMonthAgo = $today->subMonth();
$oneMonthAgoId = spl_object_id($oneMonthAgo);
// 3518

息子「こんな風に書いてあげたら,自動的に新しいインスタンスで返してくれるの」

ワイ「ファーーーー」
ワイ「もうこれでええやん!」
ワイ「なんで最初から教えてくれへんかったんや!」

息子「ごめんごめん,笑」
息子「パパが本当になにも知らなくて,ついつい楽しくなっちゃった」

ワイ「(2歳に遊ばれている...)」

CarbonImmutable で書き直してみる

ワイ「じゃぁさっきのダイエット管理アプリを」
ワイ「CarbonImmutable で書き直してみるか...!」

- use Carbon\Carbon;
+ use Carbon\CarbonImmutable;

// 今日の日付を CarbonImmutable で取得する
- $today = Carbon::today('Asia/Tokyo');
+ $today = CarbonImmutable::today('Asia/Tokyo');

// 1ヶ月前の日付を取得する
$oneMonthAgo = $today->subMonth();

ワイ「よし...!できたで!」
ワイ「ブラウザをリロードしてみると...」

ダイエットツール君「よく頑張ったな!1痩せコイン!」

ワイ「やった〜!」
ワイ「ちゃんと表示されたで!」

その夜

ワイ「ダイエット管理ツールの新機能もできたことだし」
ワイ「今日はご褒美にアイス6個食べるで!」

息子「(だめじゃん...)」
息子「(これじゃいつまで経っても痩せないよ...)」
息子「(こっそり Carbon に戻しとこ)」

  1. オライリー社が出版している C 言語の書籍.表紙に牛の絵が書いてある.
    51HY6s6u2LL.SL500.jpg

  2. ゲームボーイ版ポケモン(赤など)で,セレクトを沢山押してポケモンのレベルを 100 にしたり,マスターボールを 99 個にしたりするバグ技のこと.

78
17
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
78
17