You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP7下Laravel日期过滤报错,PHP5.6正常的问题排查与修复

解决PHP7 Laravel中“Only variables should be passed by reference”错误

嘿,这个问题我太熟悉了——同样的代码在PHP5.6纯环境里跑完全正常,到PHP7的Laravel项目就报错,核心原因是PHP7对参数传递的规则做了更严格的约束。咱们一步步来拆解:

问题重现

你遇到的错误提示是Only variables should be passed by reference,报错的代码行是:

$result[array_pop(array_keys($result))][] = $val;

你的完整业务代码如下:

public function filter(Request $request) {
    $time = new DateTime('now');
    $now = $time->modify('first day of this month')->format('Y-m-d');
    $last_year = $time->modify('-1 year')->format('Y-m-d');
    // get a list of dates from past year
    $all = $this->dateRange($last_year, $now);
    foreach($request->dates as $date) {
        // get date ranges of completed addresses
        $range = $this->dateRange($date[0], $date[1]);
        // return an array of unconfirmed dates for addresses
        $all = array_diff($all, $range);
    }
    if(empty($all)) {
        $time = new DateTime('now');
        $now = $time->format('M Y');
        $last_year = $time->modify('-1 year')->format('M Y');
        $dates[] = array(
            $last_year,
            $now
        );
    } else {
        $time = new DateTime('now');
        $last_year = $time->modify('first day of this month')->modify('-1 year');
        $result = array();
        foreach ($all as $key => $val) {
            if ($last_year->add(new DateInterval('P1D'))->format('Y-m-d') != $val) {
                $result[] = array();
                $last_year = new DateTime($val);
            }
            $result[array_pop(array_keys($result))][] = $val;
        }
        foreach($result as $array) {
            $dates[] = array(
                (new DateTime($array[0]))->format('M Y'),
                (new DateTime(end($array)))->format('M Y')
            );
        }
    }
    return response()->json($dates);
}
private function dateRange($start, $end) {
    $period = new DatePeriod(
        new DateTime($start),
        new DateInterval('P1D'),
        new DateTime($end)
    );
    foreach($period as $key => $value) {
        $range[] = $value->format('Y-m-d');
    }
    return $range;
}

错误原因

PHP7收紧了引用传递参数的规则:像array_pop()这类函数,要求传入的参数必须是一个可被引用的变量,因为函数内部会修改这个参数(移除数组最后一个元素)。

在PHP5.6里,允许你直接把array_keys($result)这种临时表达式(它返回的是一个全新的临时数组,不是存在内存里的变量)传给array_pop();但PHP7开始明确禁止这种写法——临时表达式无法被引用,所以就抛出了这个错误。

修复方案

有两种靠谱的修复方式,推荐第二种,性能更好代码也更清晰:

方式1:先把临时数组转为变量

把array_keys($result)的结果先存到一个变量里,再传给array_pop():

// 替换原来的报错行
$resultKeys = array_keys($result);
$lastResultKey = array_pop($resultKeys);
$result[$lastResultKey][] = $val;

方式2:直接跟踪最后一个子数组的键名(更高效)

你的逻辑是往$result的最后一个子数组里追加元素,完全没必要每次都生成整个数组的键列表。咱们可以在初始化时跟踪最后一个子数组的键名:

// 初始化$result时,同时跟踪最后一个子数组的键
$result = array();
$lastSubarrayKey = -1;
foreach ($all as $key => $val) {
    if ($last_year->add(new DateInterval('P1D'))->format('Y-m-d') != $val) {
        $result[] = array();
        $lastSubarrayKey++; // 新增子数组,键名+1
        $last_year = new DateTime($val);
    }
    // 直接用跟踪的键名访问最后一个子数组
    $result[$lastSubarrayKey][] = $val;
}

这种方式避免了每次循环都调用array_keys()和array_pop(),性能更优,逻辑也更直观。

另外,代码里(new DateTime(end($array)))->format('M Y')这行,虽然现在没报错,但end()同样要求参数是变量引用,为了稳妥可以提前存变量:

$lastDateInArray = end($array);
(new DateTime($lastDateInArray))->format('M Y')

内容的提问来源于stack exchange,提问作者Peter Griffin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:16:00