SplStack和SplQueue基于双向链表,push/pop/enqueue/dequeue均为O(1),而数组模拟队列时array_shift为O(n),栈场景二者性能相当,队列场景SPL显著更优。
直接上手 SPL,别从“什么是迭代器”开始读文档。它不是理论课,是 PHP 里现成能替换掉你那些
+
+
套路的工具箱——用错地方才需要重学。
什么时候该用
而不是数组模拟栈
当你写
然后
,且频繁执行(比如解析嵌套表达式、回溯路径),就该换
。
是 C 实现的双向链表,
/
/
全是 O(1),而数组的
虽快,但
或中间插入会触发整块内存重排
它实现了
和
,可直接
和
,不用再
或
空栈调用
会抛
,不是静默返回
或
—— 这是好事,逼你显式处理边界,而不是靠
补丁式防御
的 enqueue/dequeue 和数组的差异在哪
别用
+
模拟队列:后者时间复杂度是 O(n),每次删头都要搬动后面所有元素。
的
和
都是 O(1),底层不挪数据,只改指针
它支持
,所以能写
查看队首(但不推荐,语义不清;用
更安全)
注意:它不支持随机访问,
会报
,不是像数组那样返回
如果业务需要“查看但不取出”,
没有内置
,得自己封装:
或先
再
回去(不推荐)
为什么
比普通数组更适合配置或 DTO 场景
当你把配置项、API 返回结构、表单数据当成“数据容器”而非“计算载体”时,
就比原生数组更可控。
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
立即学习
“
PHP免费学习笔记(深入)
”;
它能被序列化(
),原生数组也能,但
可以绑定自定义序列化逻辑(通过实现
接口)
支持对象式访问:
或
,避免
这种防御式写法泛滥
可挂载迭代器行为:传入
或
控制属性/键值访问权限,防止意外写入非法字段
它不是数组的“升级版”,而是“约束版”:不能用
合并,不能用
,强制你走
/
,这对数据一致性是加分项
真的比普通数组快?什么情况下值得切
只在明确知道长度且极少变动时才考虑它,否则就是给自己加维护成本。
它在内存中是连续分配的,索引访问是纯指针偏移,比 PHP 数组(哈希表实现)的键查找快 2–3 倍,尤其在循环中
百万次以上时可见差距
必须提前指定大小:
,之后不能
,不能
,越界写入直接 fatal error
不支持字符串键,不支持
直接遍历(需用
+
手动循环)
它不实现
默认接口,要手动启用:
,否则
会失败
真正容易被忽略的点是:SPL 类大多为
,不能继承。想扩展功能,得用组合(wrapper class)或装饰器模式,而不是习惯性写
—— 那会直接报错。
array_pusharray_shiftforeachSplStackarray_push($stack, $item)array_pop($stack)SplStackSplStackpushpoptoparray_poparray_unshiftCountableIteratorcount($stack)foreach ($stack as $v)count($arr)array_values($arr)pop()RuntimeExceptionnullfalseif (!empty($arr))SplQueuearray_pusharray_shiftSplQueueenqueue()dequeue()ArrayAccess$queue[0]bottom()$queue[5]RuntimeExceptionNULLSplQueuepeek()current($queue->getIterator())dequeueenqueueArrayObjectArrayObjectserialize()ArrayObjectSerializable$obj->name$obj['name']$arr['name'] ?? nullArrayObject::STD_PROP_LISTArrayObject::ARRAY_AS_PROPS+array_mergeappend()offsetSet()SplFixedArray$arr[$i]new SplFixedArray(1000)pushresizeforeachgetSize()offsetGet($i)ArrayAccessnew SplFixedArray(1000)->setFlags(SplFixedArray::USE_KEY_AS_INDEX)offsetGetfinalclass MyStack extends SplStack