Carbon 是一个 PHP 中处理日期时间的扩展包,Laravel 默认集成了该扩展包。需要注意的是,Carbon 实例是一个对象,对象赋值时,默认是引用传递。PHP 传值和传引用。
例如在商城系统中,我们要统计最近三天的订单数据。
示例代码如下:
.
.
.
public function handle()
{
$start = Carbon::make('2019-10-11');
$end = Carbon::make('2019-10-13');
for ($day = $start; $day <= $end; $day->addDay()) {
$this->calculate($day);
}
.
.
.
}
.
.
.
protected function calculate(Carbon $day)
{
// 当天的起始和结束时间
$start_of_day = $day->startOfDay()->toDateTimeString();
$end_of_day = $day->endOfDay()->toDateTimeString();
// 查询当天的订单
.
.
.
}
.
.
.
实际 calculate()
方法却只运行了两次,$day
依次为 2019-10-11 00:00:00
和 2019-10-12 23:59:59
,和我们预期的运行三次并不相符。
原因在于,将 Carbon 实例作为参数传递给 calculate()
函数时,默认是引用传递,对其修改会影响原来的值。如果想在内存中生成两个一样的对象或者创建一个对象的副本,可以使用 clone
。所以正确的写法是:
.
.
.
protected function calculate(Carbon $day)
{
// 先克隆一个副本,对副本操作,避免影响原值
$target_day = clone $day;
// 当天的起始和结束时间
$start_of_day = $target_day->startOfDay()->toDateTimeString();
$end_of_day = $target_day->endOfDay()->toDateTimeString();
// 查询当天的订单
.
.
.
}
.
.
.
PHP 传参时,如果变量是非对象,会直接拷贝其值,对这个变量做任何改动都不影响原值。传引用或者传对象,会传真实的内存地址,对这个变量做的改动会影响原值。Carbon 实例就是对象。