Laravel 5.4.28生产环境count()报错,开发环境正常,求原因及解决办法
这个报错我之前帮同行排查过,核心是PHP 7.2对count()函数的参数校验变得严格了,而Laravel 5.4.28的代码没适配这个变化:
- 在PHP 7.0及更早版本里,给
count()传null或者非Countable类型的变量,会默认返回0且不报错; - 但PHP 7.2开始,这种情况直接就抛出
count(): Parameter must be an array or an object that implements Countable的错误。
你的Artwork模型用了Searchable trait,结合报错位置在Builder.php第936行,大概率是Laravel查询构建器(或是Scout扩展的查询逻辑)在某些场景下,给count()传入了非Countable的值(比如null)——这个问题在PHP 7.0被“包容”了,但到PHP 7.2就触发了错误。
补充个背景:Laravel 5.4的官方兼容范围是PHP 5.6.4 ~ PHP 7.1,PHP 7.2是Laravel 5.4发布后才推出的,所以框架本身没针对7.2做适配,这也是问题出现的根本原因。
按优先级推荐以下方案:
1. 升级Laravel 5.4到最新补丁版本
Laravel 5.4的最后一个稳定版本是5.4.36,官方在后续补丁里修复了不少PHP 7.2的兼容性问题,包括Builder.php里count()的调用逻辑。执行命令升级:
composer require laravel/framework:5.4.36 --no-update composer update laravel/framework --with-dependencies
2. 升级Laravel Scout到对应兼容版本
如果你用的Scout版本比较旧,也可能存在PHP 7.2的适配问题。针对Laravel 5.4,Scout的兼容版本是3.x系列,升级到最新的3.x版本:
composer require laravel/scout:^3.0 --no-update composer update laravel/scout --with-dependencies
3. 临时修复框架代码(仅应急用,不推荐)
如果暂时没法升级框架,可以手动修改vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php第936行的代码,在调用count()前先做类型检查:
原来的代码大概是这样:
$count = count($this->bindings);
修改成:
$bindings = $this->bindings ?? []; $count = is_array($bindings) || $bindings instanceof \Countable ? count($bindings) : 0;
注意:修改框架核心文件会导致后续更新冲突,所以这只是临时应急方案,优先选升级框架。
内容的提问来源于stack exchange,提问作者Khaled Al-Shehri

