参数展开(...)必须放在参数列表末尾;??=仅在左侧为null或未定义时赋值,对false、0、''无效。

参数展开(...)必须放在参数列表末尾
PHP 7.3+ 支持在函数调用中用 ... 展开数组,但语法限制很硬:展开操作符只能出现在参数列表最后,不能穿插在其他参数中间。
常见错误现象是 PHP 报错 Parse error: syntax error, unexpected '...' (T_ELLIPSIS),尤其当写成类似 func($a, ...$args, $b) 这种形式时——这在 PHP 中非法,且至今未支持。
- 正确写法:
func($a, $b, ...$args)或纯展开func(...$args) - 如果需要“中间插入”,得先手动合并数组,比如
$all = array_merge([$a, $b], $args); func(...$all) - 关联数组展开后仍按索引顺序传参,键名被忽略;若函数依赖命名参数(如 PHP 8.0+ 的命名参数),
...不适用
is_countable() 能防 count() 警告,但不等于“安全调用”
PHP 7.3 新增的 is_countable() 主要解决对不可数对象调用 count() 时触发的 E_WARNING。但它只判断类型,不保证 count() 执行一定成功。
典型踩坑场景:对象实现了 Countable 接口,但 count() 方法内部抛出异常(比如 DB 查询失败导致的逻辑异常),is_countable() 仍返回 true,后续调用照样崩。
立即学习“PHP免费学习笔记(深入)”;
- 推荐组合用法:
if (is_countable($var) && !is_array($var)) { $n = @count($var); }—— 对对象加错误抑制更稳妥 - WordPress 4.9.6+ 已自带兼容层,但低版本 PHP 中自行 polyfill 时,别只检查
instanceof Countable,还要兜底is_array() -
is_iterable()是 PHP 7.1 加入的,和is_countable()无替代关系:前者管“能否 foreach”,后者管“能否 count”
??= 和 += 看似都赋值,语义完全不同
??= 是空合并赋值,只在左侧为 null 或未定义时才写入;+= 是数组合并赋值,行为取决于键是否存在、是否索引数组。
最容易混淆的是处理配置数组时误用 += 替代 ??=:比如 $cfg['timeout'] += 5000 会尝试做加法运算,若 $cfg['timeout'] 是字符串或未定义,直接报 Warning: A non-numeric value encountered 或 Notice: Undefined index。
- 设默认值用
??=:$cfg['timeout'] ??= 5000; - 合并配置用
+(非破坏性)或array_replace_recursive()(深度合并),别用+=处理关联数组,默认行为是覆盖同名键,且会重排索引键 -
??=不支持表达式左值,比如$arr[$key] ??= 'val'合法,但($obj->prop) ??= 'val'在 PHP 7.3–8.0 中不支持(需 PHP 8.1+)
array_key_first() 和 array_key_last() 不改变数组指针
这两个函数是 PHP 7.3 为替代 reset() + key() 和 end() + key() 而生,核心优势就是“不干扰内部指针”。但很多人仍习惯性接着调用 current() 或 next(),结果拿到的不是预期值。
例如:$k = array_key_first($arr); $v = current($arr); —— 这里 $v 取到的不一定是 $arr[$k],因为 current() 读取的是当前指针位置,而 array_key_first() 并未移动指针。
- 要取首个键值对,应明确写:
$k = array_key_first($arr); $v = $arr[$k] ?? null; - 对空数组调用这两个函数返回
null,不是false,注意判空方式:if ($k !== null),而非if ($k) - 它们只适用于数组,对
Traversable对象无效;若需兼容对象,得先iterator_to_array()(但有内存风险)
??= 的 null-only 语义——看着像“默认赋值”,其实对 false、0、'' 完全不生效,这点和 JavaScript 的 ?? 一致,但和 PHP 旧习惯冲突最大。



















