空数组 [] 是真实数组,可直接操作;?array 是类型声明,表示变量可为数组或 null,语义不同。推荐用 $arr = []; 初始化确定为空的数组,函数参数等存在性不确定场景用 ?array 声明。

PHP 8.1+ 中定义“空数组”本身很简单,但真正需要关注的是:你定义的到底是「可为空的数组变量」,还是「确定为数组、且初始为空」的变量?二者语义不同,处理方式和规范也不同。关键不在“怎么写”,而在“为什么这么写”。
明确区分:空数组 [] 与可为空的数组 ?array
这是最容易混淆的第一步。
-
[] 是一个真实数组,类型就是
array,长度为 0,可用于foreach、count()、array_push()等所有数组操作,无需判空即可安全使用。 -
?array 是一种类型声明,表示该变量可以是
array或null,它不承诺“一定有数组”,只承诺“如果有,那一定是数组”。函数参数或属性用它,是为了表达“这个值可能根本没传”。 - 例如:
function handleTags(?array $tags): void { ... }允许调用者传null或['php', 'web']或[];而function handleTags(array $tags): void则强制必须传数组(包括空数组),传null会直接抛TypeError。
定义确定为空数组的推荐写法
当你明确需要一个数组容器、只是暂时没数据,就用最简洁、最无歧义的方式初始化:
-
统一使用
$arr = [];—— 这是 PHP 5.4+ 官方推荐语法,比array()更短、更现代,且在 PHP 8.1+ 静态分析中识别更准确。 - 避免
$arr = array();,虽仍可用,但已过时,语义略冗长,且在严格模式下可能被 IDE 或 Psalm/PHPStan 标记为“非首选”。 - 不要用
$arr = null;后再赋值,除非你真需要延迟初始化;否则提前声明空数组,逻辑更清晰、类型更稳定。
声明可为空数组类型的规范用法
适用于函数参数、返回值、类属性等需表达“存在性不确定”的场景:
立即学习“PHP免费学习笔记(深入)”;
- 函数参数写成
function process(?array $data),而非function process($data)+ 内部手动is_array($data) || $data === null,前者由引擎强制校验,后者易漏判、难维护。 - 类属性建议配合 PHPDoc 补充说明,尤其在未启用属性类型(PHP 7.4+)或需兼容旧版本时:
/** @var array|null */ private $cache; - 返回值若可能为
null,优先用?array而非array|false或array|void,语义更精准,也符合 PSR-12 和主流框架(如 Laravel 的 Eloquent Collection 方法)惯例。
避免常见误用与陷阱
这些写法看似能跑,但破坏类型安全或埋下隐患:
- 不用
empty($arr)判断是否为“有效数组”——它对[]返回true,但空数组常常是合法状态(比如用户没选任何标签)。应改用is_array($arr) && count($arr) > 0或更稳妥的is_array($arr) && !array_is_list($arr) ? ... : ...(视业务而定)。 - 不把未初始化变量当数组用:
$items[] = 'x';虽不会报错(PHP 自动创建),但违反显式初始化原则,IDE 无法推断类型,静态分析失效,团队协作易出错。 - 数据库读取后,别直接
$row['tags'] ?? []就完事——要确认字段本身是否允许为NULL,还是数据库存了''字符串。PHP 8.1 对字符串与数组的类型区分更严格,混用易触发隐式转换警告或错误。



















