在PHP开发中,数组几乎承载了列表、缓存、配置、查询结果等多种数据形式。遇到只需要使用数组里某一段数据的场景时,最直接的做法就是调用 array_slice 或者 array_splice。不过这两个函数虽然名字相近,行为却截然不同:一个保持原数组不动,另一个会直接改写原数组。理解它们处理偏移量、长度和键名的方式,可以避免很多数据错乱问题。

一、array_slice:安全地取出数组片段
array_slice 的作用是从数组中截取一段并返回新数组,原数组不会被修改。它的函数签名是 array_slice(array $array, int $offset, ?int $length = null, bool $preserve_keys = false): array。其中 offset 表示起始位置,正数从前往后数,负数从尾部往前数;length 表示截取长度,正数表示取几个元素,负数表示排除末尾的多少个元素;第四个参数 preserve_keys 用于控制数字键是否保留。
对于普通的索引数组,默认情况下截取后的数字键会被重新索引,从 0 开始连续编号。如果希望保留原来的数字键,可以把第四个参数设为 true。下面通过一段代码观察实际效果:
<?php $arr = ['a', 'b', 'c', 'd', 'e']; // 从偏移量1开始截取3个元素 $part1 = array_slice($arr, 1, 3); print_r($part1); // 取最后2个元素 $part2 = array_slice($arr, -2); print_r($part2); // 去掉最后1个元素,保留前面的所有元素 $part3 = array_slice($arr, 0, -1); print_r($part3); ?>
运行后可以看到,$part1 的值是 b、c、d,键名默认为 0、1、2;$part2 的值是 d、e,同样重新索引;$part3 则是 a、b、c、d,相当于把最后一个元素排除掉了。这个特性在处理列表数据时非常方便,比如取前几条做预览,或者去掉最后一条汇总数据。
关联数组的情况略有不同。array_slice 默认不会重置字符串键名,但对于数字键仍然会重新索引。如果原数组既有字符串键又有数字键,要想保留所有数字键,就需要显式传递 true:
<?php
$user = [
'id' => 1,
'name' => 'Tom',
'email' => 'tom@ipipp.com',
'phone' => '123456'
];
$part = array_slice($user, 1, 2);
print_r($part);
$list = [10, 20, 30, 40, 50];
$slice = array_slice($list, 1, 2, true);
print_r($slice);
?>
第一段输出中,name 和 email 的字符串键名保持不变。第二段输出中,因为传入了 true,所以截取出来的两个元素仍然使用原来的键 1 和 2。如果不传 true,键名会变成 0 和 1。这个细节在需要保持数组索引与原始数据一一对应时尤其重要,比如用数组下标作为用户 ID 或者订单编号的映射。
二、array_splice:直接修改原数组的截取与替换
array_splice 和 array_slice 最本质的区别在于它会直接修改传入的数组,并且返回被移除的那部分元素。它的函数签名是 array_splice(array &$array, int $offset, ?int $length = null, mixed $replacement = []): array。由于第一个参数是引用传递,调用后原数组会立刻发生变化,所以适合用来真正从数组中删除、替换或者插入元素。
典型的删除操作如下:
<?php $arr = ['a', 'b', 'c', 'd', 'e']; $removed = array_splice($arr, 1, 2); print_r($arr); print_r($removed); ?>
执行后原数组变成 a、d、e,$removed 则返回 b、c。值得留意的是,array_splice 对数字键的处理和 array_slice 类似,会重新索引原数组和返回数组中的数字键。如果原数组包含字符串键,字符串键仍然会保留,但它不会像 array_slice 那样提供 preserve_keys 参数。
array_splice 还支持替换和插入。将 length 设为 0 时表示不删除元素,只把 replacement 插入到 offset 位置;如果同时给出 replacement 和 length,就会先删掉指定范围,再把 replacement 放进去。看下面的代码:
<?php $arr2 = ['x', 'y', 'z']; array_splice($arr2, 1, 0, ['M', 'N']); print_r($arr2); $arr3 = [1, 2, 3, 4, 5]; $removed3 = array_splice($arr3, -2, 2, [8, 9]); print_r($arr3); print_r($removed3); ?>
第一段输出会得到 x、M、N、y、z,说明 M、N 被插入到了索引 1 的位置。第二段使用负数 offset 定位到倒数第二个元素,删除末尾两个元素并用 8、9 替换,最终原数组变成 1、2、3、8、9。这个用法在做列表编辑、批量替换或删除指定区间数据时非常实用。
需要特别注意,array_splice 的 replacement 参数如果是一个关联数组,其键名不会保留,数字键会被重新索引。因此在处理关联数组时,如果依赖键名做业务逻辑,建议先单独取出元素,再手动构造新数组,避免因为键名丢失造成数据混乱。
三、截取后的键名重置与分块处理技巧
数组截取之后经常遇到数字键不连续的情况,比如用 array_slice 并传入 preserve_keys 为 true,或者用 array_splice 删除中间元素。此时如果后续代码依赖连续的数字下标,就需要调用 array_values 重新建立索引。这个函数会返回一个从 0 开始连续编号的新数组,原数组不受影响。
<?php $list = [10, 20, 30, 40, 50]; $slice = array_slice($list, 1, 2, true); print_r($slice); $reindexed = array_values($slice); print_r($reindexed); ?>
上面代码里,$slice 的键名是 1 和 2,经过 array_values 处理后,$reindexed 的键名变成 0 和 1,元素值不变。这个组合在数据库查询结果、文件读取行、日志分析等场景中经常出现,可以保证后续遍历和 json 编码时得到标准的数组结构。
如果面对的是一个大数组,想把数据均匀切分成若干块,array_chunk 会比手动循环截取更简洁。它的第三个参数同样可以控制是否保留原来键名,默认会重新索引每一块中的数字键。
<?php $data = range(1, 25); $chunks = array_chunk($data, 10); print_r($chunks); ?>
运行后数组被分成 10、10、5 三块。对于分页展示、批量任务队列、数据导出等需求,可以直接把每一块当作一次处理单元。分页时也常直接用 array_slice 计算偏移量,例如每页 20 条,第二页从第 20 条开始取:
<?php $records = range(1, 200); $page = 2; $pageSize = 20; $pageData = array_slice($records, ($page - 1) * $pageSize, $pageSize); print_r($pageData); ?>
这种计算方式清晰直接,但要注意 offset 如果超出数组长度,array_slice 会返回空数组而不是报错。实际项目中最好先判断 count($records) 和 offset 的关系,避免把空结果当成有效数据返回给前端。对 array_splice 来说,offset 越界同样不会抛出异常,但很可能删不到任何元素,调用后需要检查原数组长度变化是否符预期。
总结一下,array_slice 适合只读取片段而保持原数组不变,array_splice 适合真正删改原数组,array_chunk 适合把大数组分块,array_values 则用来解决截取后数字键不连续的问题。把几个函数配合使用,就能覆盖绝大多数 PHP 数组截取和重组的业务场景。
PHP数组截取array_slicearray_splice修改时间:2026-09-30 16:30:18