1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PHP の Carbon 型オブジェクトを使い回してはいけない

1
Posted at

Carbon 型に実装されているメソッドは破壊的メソッド

PHP で時刻を扱うには Carbon というライブラリが使用できます。

ですが、Carbon\Carbon 型のオブジェクトは可変 (mutable) であり、実装されているメソッドは破壊的 (destructive) メソッドのため、オブジェクトそのものの値が変更 (modify) されてしまいます。

when you use a modifier on a Carbon instance, it modifies and returns the same instance
https://carbon.nesbot.com/docs/

carbon_example.php
<?php

require_once "vendor/autoload.php";
use Carbon\Carbon;

$now = Carbon::now();
print("now        = " . $now . "\n");

$myDatetime = $now->startOfHour();
print("now        = " . $now . "\n");
print("myDatetime = " . $myDateTime . "\n");

// 何なら代入する必要もない
$myDatetime->addMinutes(30);
print("now        = " . $now . "\n");
print("myDatetime = " . $myDateTime . "\n");
$ php -f carbon_example.php
now        = 2023-04-22 21:28:23
now        = 2023-04-22 21:00:00
myDatetime = 2023-04-22 21:00:00
now        = 2023-04-22 21:30:00
myDatetime = 2023-04-22 21:30:00

ですので、値を再利用したい場合は copy() などを挟む必要があります。

carbon_example2.php
 <?php

 require_once "vendor/autoload.php";
 use Carbon\Carbon;

 $now = Carbon::now();
 print("now        = " . $now . "\n");

+// copy() を挟むことで元のオブジェクトに影響を与えない
-$myDatetime = $now->startOfHour();
+$myDatetime = $now->copy()->startOfHour();
 print("now        = " . $now . "\n");
 print("myDatetime = " . $myDateTime . "\n");

-$myDatetime->addMinutes(30);
+$myDatetime->copy()->addMinutes(30);
 print("now        = " . $now . "\n");
 print("myDatetime = " . $myDateTime . "\n");
$ php -f carbon_example2.php
now        = 2023-04-22 21:36:35
now        = 2023-04-22 21:36:35
myDatetime = 2023-04-22 21:00:00
now        = 2023-04-22 21:36:35
myDatetime = 2023-04-22 21:00:00

CarbonImmutable を使おう

しかし、それではくどいため CarbonImmutable を使うのが良いかもしれません。この型を使うと、addMinutes などのメソッドを呼び出しても元のインスタンスは変更されず、新しいインスタンスを戻り値として返します。

when you use it on CarbonImmutable, it returns a new instances with the new value.

carbon_example3.php
 <?php

 require_once "vendor/autoload.php";
-use Carbon\Carbon;
+use Carbon\CarbonImmutable;

-$now = Carbon::now();
+$now = CarbonImmutable::now();
 print("now        = " . $now . "\n");

 $myDatetime = $now->startOfHour();
 print("now        = " . $now . "\n");
 print("myDatetime = " . $myDateTime . "\n");

 $myDatetime->addMinutes(30);
 print("now        = " . $now . "\n");
 print("myDatetime = " . $myDateTime . "\n");
$ php -f carbon_example3.php
now        = 2023-04-22 21:40:03
now        = 2023-04-22 21:40:03
myDatetime = 2023-04-22 21:00:00
now        = 2023-04-22 21:40:03
myDatetime = 2023-04-22 21:00:00

おわりに

他にもハマりそうな人が居るかもしれない思ったので記事にしました。公式ドキュメントのかなり最初の方に書かれているので、もしかしたら自分以外の人はそんなミスは犯さないのかもしれませんが……orz

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?