← PHP array_reduce()函数:用回调把数组归约为单值的实战教程 没有下一篇了 →

PHP array_replace()函数:用后续数组覆盖前一个数组的实战教程

著
原创 2026-10-08 PHP 已有人查阅

一、array_replace()的语义

这个函数做的事可以用一句话概括:以第一个数组为底,用后面的数组按"键"去覆盖它。

注意关键词是"按键"。它不关心值的类型,也不做递归合并,只看键名是否相同。键名相同就替换,键名不存在就追加。理解这一点,后面所有行为都能推出来。

和array_merge()容易混。array_merge()对数字键是重新编号追加,对字符串键是后者覆盖前者;array_replace()对数字键和字符串键一视同仁,都是同键覆盖、无键追加。这是两者最本质的区别。

二、函数原型与参数

array_replace(array $array1, array ...$replacements): array
参数 说明 是否必需
array1 被替换的基准数组 必需
replacements 一个或多个替换数组 可选

返回值:替换后的新数组。原数组不受影响。如果传入的参数不是数组,返回null。

替换数组可以有多个,后面的数组会覆盖前面数组的同名键,顺序不能颠倒。

三、字符串键的覆盖

字符串键是最直观的场景:

<?php
$config = array("j" => "java", "p" => "php");
$override = array("j" => "javatpoint");

print_r(array_replace($config, $override));

输出:

Array
(
    [j] => javatpoint
    [p] => php
)

键j被替换,键p因为第二个数组里没有,保留原值。这就是配置覆盖的典型形态。

再看一个多数组叠加的例子:

<?php
$a1 = array("a" => "Sonoo", "java");
$a2 = array("a" => "javatpoint", "b" => "PHP");

print_r(array_replace($a1, $a2));

输出:

Array
(
    [a] => javatpoint
    [0] => java
    [b] => PHP
)

字符串键a被覆盖,数字键0保留,新键b追加。

四、数字键的覆盖,这是重点

很多教程对数字键一笔带过,实际项目里这里最容易出问题。看例子:

<?php
$city1 = array("a" => "Patna", "b" => "chennai");
$city2 = array("a" => "Pataliputra", "Noida");

print_r(array_replace($city1, $city2));

输出:

Array
(
    [a] => Pataliputra
    [b] => chennai
    [0] => Noida
)

$city2里的"Noida"没有指定键,PHP给它分配了数字键0。$city1里没有0号键,所以直接追加。如果$city1里本来就有0号键,就会被覆盖。

更典型的是下面这个:

<?php
$player1 = array("sachin", "sehwag", "kapil", "rahul");
$player2 = array(0 => "rohit", 4 => "klrahul");
$player3 = array(0 => "arjun");

$res = array_replace($player1, $player2, $player3);
print_r($res);

输出:

Array
(
    [0] => arjun
    [1] => sehwag
    [2] => kapil
    [3] => rahul
    [4] => klrahul
)

逐个键看:

  • 键0:先被$player2的rohit覆盖,再被$player3的arjun覆盖,最终是arjun。

  • 键1、2、3:后续数组没有这些键,保留$player1的原值。

  • 键4:$player2新增,追加为klrahul。

这里没有发生任何"重新编号"。数字键0到4的对应关系是稳定的,这正是array_replace()和array_merge()在数字键上的分水岭。用array_replace()处理带固定下标的数组时,下标不会被打乱。

五、与array_merge、array_replace_recursive的取舍

函数 数字键行为 字符串键行为 嵌套数组
array_replace() 同键覆盖,无键追加 同键覆盖 不递归,整体替换
array_merge() 重新编号追加 同键覆盖 不递归
array_replace_recursive() 同键覆盖 同键覆盖 递归逐层替换
+运算符 同键保留左侧 同键保留左侧 不递归

选择原则:

  • 需要保留数字键的下标语义,用array_replace()。

  • 合并列表类数据、下标无意义,用array_merge()。

  • 多层配置需要逐层覆盖,用array_replace_recursive()。

  • 只想要"补齐缺失键"、已有键不覆盖,用+运算符。

个人经验:做过一个多环境配置系统,默认配置和用户配置都是嵌套数组。一开始用array_replace()合并,结果用户只改了数据库密码,整个database子数组把默认的host、port全顶掉了,连接直接失败。换成array_replace_recursive()后,只覆盖用户显式指定的键,其余保留。嵌套配置用array_replace()是常见的误用,这是踩过坑才记住的。

另一个经验:处理分页数据时,接口返回的数组带固定数字下标,前端按位置取值。这种场景如果用array_merge()合并默认值和返回值,下标会被重排,前端全乱。array_replace()在这里才合适。

六、项目实例

实例一:代码号学习编程·多环境配置覆盖

<?php
$default = [
    'host' => 'localhost',
    'port' => 3306,
    'user' => 'root',
];

$userConfig = [
    'host' => '192.168.1.10',
    'user' => 'app',
];

$config = array_replace($default, $userConfig);
print_r($config);

输出:

Array
(
    [host] => 192.168.1.10
    [port] => 3306
    [user] => app
)

只覆盖用户指定的两项,port保留默认值。单层配置这样用没问题,多层记得换递归版本。

实例二:代码号学习编程·默认参数补全

<?php
$defaults = ['limit' => 20, 'offset' => 0, 'sort' => 'id'];
$input = ['limit' => 50, 'sort' => 'name'];

$params = array_replace($defaults, $input);
print_r($params);

输出:

Array
(
    [limit] => 50
    [offset] => 0
    [sort] => name
)

接口参数处理里这个模式很常见:先铺默认值,再用入参覆盖,之后拿到的就是完整参数集。

实例三:代码号学习编程·多来源配置叠加

<?php
$base = ['debug' => false, 'cache' => true, 'log' => 'file'];
$env = ['debug' => true];
$cli = ['log' => 'stdout'];

$final = array_replace($base, $env, $cli);
print_r($final);

输出:

Array
(
    [debug] => 1
    [cache] => 1
    [log] => stdout
)

优先级从右往左,越靠后的数组优先级越高。配置系统的分层覆盖就是这个思路。

七、踩坑记录

坑一:把array_replace()当成递归合并。嵌套数组会整体替换,不会逐层合并。多层结构必须用array_replace_recursive()。

坑二:数字键下标和array_merge()混用。需要保留下标语义时用了array_merge(),下标被重排,数据对不上。判断标准是"下标有没有业务含义"。

坑三:参数顺序颠倒。array_replace($override,$base)和array_replace($base,$override)结果不同。前者是"用base覆盖override",写反了逻辑正好反过来,而且代码看起来还挺合理,不容易发现。

坑四:以为会修改原数组。array_replace()返回新数组,原数组不变。如果后面继续用原数组,拿到的还是旧值。

坑五:传入非数组参数。参数中有非数组时返回null,后续对null做数组操作会报错。调用前应确保参数类型正确。

八、本节课程知识要点

  1. array_replace()按"键"覆盖,同键替换,无键追加,不重排下标。

  2. 数字键和字符串键行为一致,这是与array_merge()的核心差异。

  3. 多个替换数组时,后面的覆盖前面的,顺序决定优先级。

  4. 嵌套数组不递归,整体替换;需要逐层覆盖用array_replace_recursive()。

  5. 返回新数组,原数组不变;参数非法时返回null。

  6. 只补缺失键、不覆盖已有键,用+运算符更合适。

九、常见问题

问:array_replace()会改变原数组吗?

不会。它返回替换后的新数组,原数组保持原样。

问:数字键是怎么处理的?

同键覆盖,无键追加,不重新编号。数字下标会被保留。

问:和+运算符有什么区别?

+运算符是"左侧优先",同键时保留左侧的值;array_replace()是"右侧优先",同键时右侧覆盖左侧。

问:替换数组里的值为null会怎样?

会正常覆盖,键对应的值变成null。这和"键不存在"是两回事,不会触发保留原值的逻辑。

问:能用来做数组合并吗?

能,但要看数字键是否需要保留。下标无意义的列表合并,array_merge()更贴合语义。

← PHP array_reduce()函数:用回调把数组归约为单值的实战教程 没有下一篇了 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号