PHP Carbon类更改了我的原始变量值

63

我正在创建一个类似日历的东西,尝试制作几个导航按钮,我正在使用Carbon来创建日期。

这是控制器中的代码:

if ($date == null) {
    $date = \Carbon\Carbon::now();
} else {
    $date = \Carbon\Carbon::createFromFormat('Y-m-d', $date);
}
$navDays = [
    '-7Days' => $date->subDay('7')->toDateString(),
    '-1Day'  => $date->subDay('1')->toDateString(),
    'Today'    => $date->today()->toDateString(),
    '+1Day'  => $date->addDay('1')->toDateString(),
    '+7Days' => $date->addDay('7')->toDateString()
];

然后在我的看法中,我正在做这件事:

@foreach($navDays as $key => $i)
    <li>
        <a href="/planner/bookings/{{ $i }}" class="small button">
            {{ $key }}
        </a>
    </li>
@endforeach

问题在于,碳似乎在创建数组时更改了$date,因为这些是我得到的日期(其中$date设置为2015-11-29):

<ul class="button-group even-5">
    <li><a href="/planner/bookings/2015-11-22" class="small button">-7Days</a></li>
    <li><a href="/planner/bookings/2015-11-21" class="small button">-1Day</a></li>
    <li><a href="/planner/bookings/2015-12-22" class="small button">Today</a></li>
    <li><a href="/planner/bookings/2015-11-22" class="small button">+1Day</a></li>
    <li><a href="/planner/bookings/2015-11-29" class="small button">+7Days</a></li>
</ul>

有人知道我做错了什么吗?

3个回答

123

当您对Carbon对象运行这些方法时,它会更新对象本身。因此,addDay()将Carbon的值向前移动一天。

以下是您需要执行的操作:

$now = Carbon::now();

$now->copy()->addDay();
$now->copy()->addMonth();
$now->copy()->addYear();
// etc...

复制方法实质上是创建一个新的Carbon对象,您可以在不影响原始$now变量的情况下对其进行更改。

总之,复制Carbon实例的方法有:

  • copy
  • clone - copy的别名

请查看文档:https://carbon.nesbot.com/docs/


4
从 Laravel 5.8 版本开始,您也可以使用 $now->toImmutable()->addDay() 来实现。 - Amir Hossein Abdollahi
@AmirHossein,你应该将这个作为完整的答案添加进去。使用不可变对象而不是克隆可变对象是一种更清晰的方法。 - benjaminhull

17

问题在于您假设subDay()/addDay()方法不改变日期对象,但实际上它们只是使用DateTime对象的modify()方法进行了包装:

DateTime::modify -- date_modify — 更改时间戳

(我加粗了部分文字)

因此,请使用

$navDays = [
    '-7Days' => (clone $date)->subDay('7')->toDateString(),
    '-1Day'  => (clone $date)->subDay('1')->toDateString(),
    'Today'  => (clone $date)->today()->toDateString(),
    '+1Day'  => (clone $date)->addDay('1')->toDateString(),
    '+7Days' => (clone $date)->addDay('7')->toDateString()
];

这给了我一个错误: 语法错误,意外的'->'(T_OBJECT_OPERATOR),期望']' 我需要事先设置它们,然后将它们添加到数组中吗? - Johan Björklund
抱歉,我意识到我在我的php7环境中测试了,没有考虑到它不能与PHP5一起使用。 - Mark Baker
16
Carbon也有一个复制方法,因此您可以像这样做... $date->copy()->subDay('7')->toDateString() - nrivero
http://php.net/manual/en/class.datetime.php 与 http://php.net/manual/en/class.datetimeimmutable.php。Carbon 基于第一个。 - challet

3

Doco说:

你也可以创建现有Carbon实例的copy()。 正如预期的那样,日期、时间和时区值都被复制到新实例中。

$dt = Carbon::now();
echo $dt->diffInYears($dt->copy()->addYear());  // 1

// $dt was unchanged and still holds the value of Carbon:now()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接