php 8.1起,带默认值的参数必须位于必需参数之后,否则抛argumentcounterror;修复方式为重排参数顺序或将默认值改为null判断并内部分配。

PHP 函数参数顺序错误:$xxx follows $yyy 报 Deprecated
PHP 8.0 起,函数定义中「带默认值的参数(可选参数)写在必需参数之前」会触发 Deprecated: Required parameter $xxx follows optional parameter $yyy;到 PHP 8.1,这不再只是警告——直接抛出 ArgumentCountError,调用失败。
为什么不能把 $size=30 放在 $default 前面
这不是风格问题,是 PHP 解析器的硬性规则:所有带默认值的参数必须放在参数列表末尾。否则,PHP 无法安全推断调用时哪些参数被省略、哪些被显式传入。
- 错误写法:
function make_yogurt($container, $flavour = 'raspberry', $topping) - PHP 8.0:报
Deprecated,但还能跑 - PHP 8.1+:调用
make_yogurt('bowl')就崩,报ArgumentCountError—— 因为$flavour被隐式转成必需参数,$topping却没传 - 根本原因:PHP 不允许「跳过中间参数」,命名参数(named arguments)也无法绕过这个限制
修复方式只有两种,别无选择
不能靠 error_reporting 屏蔽,那只是掩盖问题;升级到 PHP 8.1+ 后会彻底失效。必须改代码。
-
方案一(推荐):重排参数顺序 —— 把所有带默认值的参数挪到最后
例如:function make_yogurt($container, $topping, $flavour = 'raspberry') -
方案二:移除默认值,改用 null 类型声明 + 函数内判断
例如:function make_yogurt($container, $flavour, $topping = null)→ 改成function make_yogurt($container, ?string $flavour = null, $topping),再在函数体里处理if ($flavour === null) { $flavour = 'raspberry'; } - 注意:即使用了
?string,如果它仍出现在必需参数前面,同样报错 —— 类型声明不改变「位置即语义」的规则
容易忽略的兼容性陷阱
很多人只改了函数定义,却忘了检查所有调用处。
- 如果旧调用是
make_yogurt('cup', 'strawberry'),而你改成make_yogurt($container, $topping, $flavour = ...),那这次调用实际把'strawberry'当成了$topping,逻辑就错了 - WordPress 插件/主题里常见这种写法,比如
get_avatar($id_or_email, $size = 32, $default, $alt)——$size=32在中间,必须重排或拆解 - 第三方库若未适配 PHP 8.1,哪怕你自己代码没问题,调用它的函数时也会崩
最稳妥的做法:先 grep 全项目找所有含 = 的函数定义行,逐个确认位置;再用静态分析工具(如 PHPStan)扫一遍调用链。顺序错了,光改定义不够,调用也得同步对齐。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











