Skip to content

数组运算符

概述

PHP 提供了一组专门用于数组比较和合并的运算符。数组运算符的行为与标量运算符有所不同,理解它们的规则对于正确处理数组操作至关重要。

核心要点

  • + 运算符合并数组(保留键名,不覆盖已存在的键)
  • == 比较键值对是否相同(不关心顺序和类型)
  • === 比较键值对是否完全相同(关心顺序和类型)

基础概念

运算符一览

运算符名称结果
$a + $b联合$a$b 的联合($a 的键优先)
$a == $b等于$a$b 有相同的键值对
$a === $b全等$a$b 有相同的键值对,且顺序和类型相同
$a != $b不等$a 不等于 $b(与 <> 相同)
$a !== $b不全等$a 不全等于 $b
$a <> $b不等!= 相同

语法与代码示例

数组合并 +

php
<?php

declare(strict_types=1);

// + 运算符合并数组,左侧键优先
$a = ['a' => 'apple', 'b' => 'banana'];
$b = ['b' => 'blueberry', 'c' => 'cherry'];

$result = $a + $b;
print_r($result);
// ['a' => 'apple', 'b' => 'banana', 'c' => 'cherry']
// 注意:'b' 键保留了 $a 的值 'banana'

// 数字索引数组的合并
$x = [0 => 'red', 1 => 'green'];
$y = [0 => 'blue', 1 => 'yellow'];

$z = $x + $y;
print_r($z);
// [0 => 'red', 1 => 'green']
// 数字键冲突时,左侧值优先

// + 与 array_merge 的区别
$arr1 = ['a', 'b'];
$arr2 = ['c', 'd'];

// +:保留数字键,不重新索引
print_r($arr1 + $arr2);
// [0 => 'a', 1 => 'b']

// array_merge:重新索引
print_r(array_merge($arr1, $arr2));
// [0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd']

数组比较 == vs ===

php
<?php

declare(strict_types=1);

// == 相同键值对(不关心顺序和类型)
$a = ['a' => 1, 'b' => 2];
$b = ['b' => 2, 'a' => 1];
$c = ['a' => '1', 'b' => 2]; // 注意类型不同

var_dump($a == $b);  // bool(true) —— 键值对相同,顺序不重要
var_dump($a === $b); // bool(false) —— 顺序不同

var_dump($a == $c);  // bool(true) —— '1' == 1(松散比较)
var_dump($a === $c);  // bool(false) —— 类型不同

// 数字键的顺序影响 === 但不影响 ==
$x = [0 => 'a', 1 => 'b'];
$y = [1 => 'b', 0 => 'a'];

var_dump($x == $y);  // bool(true)
var_dump($x === $y); // bool(false)

// 严格比较要求键名、值和顺序完全一致
$m = [0 => 'a', 1 => 'b'];
$n = [0 => 'a', 1 => 'b'];
var_dump($m === $n); // bool(true)

不等运算符

php
<?php

declare(strict_types=1);

$a = ['a' => 1, 'b' => 2];
$b = ['a' => 1, 'b' => 3];

// != 和 <> 等价
var_dump($a != $b);  // bool(true)
var_dump($a <> $b);  // bool(true)

// !==
var_dump($a !== $b);  // bool(true)

// 不同键的数组
$c = ['a' => 1, 'c' => 2];
var_dump($a == $c);  // bool(false)
var_dump($a != $c);  // bool(true)

详细说明

== 比较规则详解

$a == $btrue 的条件:

  1. 两个数组有完全相同的键名
  2. 对应键的值松散相等(使用 == 比较)
php
<?php

declare(strict_types=1);

// 键名必须完全匹配
$a = ['name' => 'Alice'];
$b = ['Name' => 'Alice']; // 注意大小写

var_dump($a == $b); // bool(false) —— 键名不同

// 值使用松散比较
$c = [0 => false];
$d = [0 => ''];    // '' == false 为 true

var_dump($c == $d); // bool(true) —— 值松散相等

// 值类型不同但松散相等
$e = [0 => 42];
$f = [0 => '42'];  // 42 == '42' 为 true

var_dump($e == $f); // bool(true)
var_dump($e === $f); // bool(false) —— 类型不同

+ 运算符的键冲突规则

php
<?php

declare(strict_types=1);

// 关联数组:左侧键值不被覆盖
$defaults = [
    'host' => 'localhost',
    'port' => 3306,
    'charset' => 'utf8mb4',
];

$config = [
    'host' => '192.168.1.100',
    'port' => 5432,
    'timeout' => 30,
];

$merged = $defaults + $config;
print_r($merged);
// ['host' => 'localhost', 'port' => 3306, 'charset' => 'utf8mb4', 'timeout' => 30]
// host 和 port 保留了 defaults 的值!

// 如果希望 $config 的值覆盖 $defaults
$merged2 = $config + $defaults;
print_r($merged2);
// ['host' => '192.168.1.100', 'port' => 5432, 'charset' => 'utf8mb4', 'timeout' => 30]

// 多个数组合并
$a = ['x' => 1];
$b = ['y' => 2];
$c = ['z' => 3];
$all = $a + $b + $c;
print_r($all); // ['x' => 1, 'y' => 2, 'z' => 3]

+array_merge 的区别

+ 运算符在键冲突时保留左侧值,不重新索引数字键。array_merge() 在键冲突时保留右侧值,并重新索引数字键。使用前要明确你的意图。

实战示例

默认配置合并

php
<?php

declare(strict_types=1);

function mergeConfig(array $defaults, array $userConfig): array
{
    // 使用 + 确保 defaults 的值不被覆盖
    // 但新增的 userConfig 键会被添加
    return $userConfig + $defaults;
}

$defaults = [
    'debug' => false,
    'cache' => true,
    'ttl' => 3600,
    'max_connections' => 10,
];

$userConfig = [
    'debug' => true,
    'max_connections' => 20,
    'api_key' => 'secret',
];

$config = mergeConfig($defaults, $userConfig);
print_r($config);
// ['debug' => true, 'max_connections' => 20, 'api_key' => 'secret',
//  'cache' => true, 'ttl' => 3600]

数组去重比较

php
<?php

declare(strict_types=1);

function findDuplicateArrays(array $arrays): ?array
{
    $seen = [];

    foreach ($arrays as $index => $array) {
        foreach ($seen as $prevIndex => $prevArray) {
            if ($prevArray === $array) {
                return [
                    'duplicate_indices' => [$prevIndex, $index],
                    'array' => $array,
                ];
            }
        }
        $seen[$index] = $array;
    }

    return null;
}

$data = [
    ['name' => 'Alice', 'age' => 30],
    ['name' => 'Bob', 'age' => 25],
    ['name' => 'Alice', 'age' => 30], // 重复
];

$result = findDuplicateArrays($data);
var_dump($result);
// duplicate_indices: [0, 2]

数组差集与交集运算符

php
<?php

declare(strict_types=1);

// 使用数组运算符实现简单差集
$a = ['red', 'green', 'blue', 'yellow'];
$b = ['green', 'blue'];

// "在 $a 中但不在 $b 中" —— 模拟差集
// 注意:+ 运算符不能直接实现差集,需要使用数组函数
$diff = array_diff($a, $b);
print_r($diff); // ['red', 'yellow']

// 交集
$intersect = array_intersect($a, $b);
print_r($intersect); // ['green', 'blue']

// 使用 + 和 array_keys 实现键的差异
$keys1 = ['a', 'b', 'c'];
$keys2 = ['b', 'c', 'd'];

$onlyInFirst = array_diff($keys1, $keys2);
$onlyInSecond = array_diff($keys2, $keys1);

print_r($onlyInFirst);  // ['a']
print_r($onlyInSecond); // ['d']

注意事项

  • + 不重新索引数字键:这与 array_merge() 行为不同
  • == 使用松散比较[0][''] 可能被视为相等(0 == '' 在 PHP 8.0+ 中为 false
  • === 要求顺序相同['a' => 1, 'b' => 2]['b' => 2, 'a' => 1] 使用 === 比较为 false
  • 多维数组比较===== 会递归比较所有层级

最佳实践

  1. 合并配置用 +array_replace+ 左侧优先,array_replace 右侧优先
  2. 比较数组用 ===:除非明确需要松散比较
  3. 数组差集用 array_diff:不要尝试用运算符实现
  4. array_merge vs +:需要重新索引数字键用 array_merge,否则用 +
  5. 嵌套数组合并+ 只做浅层合并,深层合并需要自定义递归函数

进阶用法

调试与测试技巧

php
<?php
declare(strict_types=1);

// 单元测试辅助函数
function createTestResource(): mixed
{
    return match (true) {
        default => new stdClass(),
    };
}

// 调试输出函数
function debugOutput(mixed , string  = ''): void
{
     =  ? ": " : '';
     .= print_r(, true);
    fwrite(STDERR,  . "\n");
}

// 性能基准测试
function benchmark(callable , int  = 1000): float
{
     = hrtime(true);
    for ($i = 0; $i < $iterations; $i++) {
        $fn();
    }
    return (hrtime(true) - $start) / 1e9;
}

日志记录实践

php
<?php
declare(strict_types=1);

/**
 * 简易日志记录器
 */
class SimpleLogger
{
    private string $logFile;
    private string $level = 'INFO';

    public function __construct(string $logFile)
    {
        $this->logFile = $logFile;
    }

    public function info(string $message, array $context = []): void
    {
        $this->log('INFO', $message, $context);
    }

    public function warning(string $message, array $context = []): void
    {
        $this->log('WARNING', $message, $context);
    }

    public function error(string $message, array $context = []): void
    {
        $this->log('ERROR', $message, $context);
    }

    private function log(string $level, string $message, array $context): void
    {
        $timestamp = date('Y-m-d H:i:s');
        $contextStr = $context ? ' ' . json_encode($context, JSON_UNESCAPED_UNICODE) : '';
        $line = "[{$timestamp}] [{$level}] {$message}{$contextStr}\n";
        file_put_contents($this->logFile, $line, FILE_APPEND | LOCK_EX);
    }
}

配置与环境检测

php
<?php
declare(strict_types=1);

// 环境检测工具
class EnvironmentChecker
{
    public static function checkRequirements(array $requirements): array
    {
        $results = [];
        foreach ($requirements as $name => $check) {
            $results[$name] = is_callable($check) ? $check() : false;
        }
        return $results;
    }

    public static function getSystemInfo(): array
    {
        return [
            'php_version' => PHP_VERSION,
            'os' => PHP_OS,
            'sapi' => PHP_SAPI,
            'memory_limit' => ini_get('memory_limit'),
            'max_execution_time' => ini_get('max_execution_time'),
            'loaded_extensions' => get_loaded_extensions(),
        ];
    }
}

常见问题排查

问题可能原因解决方案
连接超时网络问题/配置错误检查配置,增加超时时间
权限不足文件/目录权限使用 chmod/chown 修正
性能下降索引缺失/数据量大添加索引,优化查询
数据不一致并发冲突/事务残留使用锁机制和事务
内存溢出大数据集/未释放资源增大内存限制,分批处理

故障排除步骤

  1. 检查错误日志和异常信息
  2. 确认配置和环境是否正确
  3. 使用调试工具逐步排查
  4. 参考官方文档查找已知问题

版本兼容性说明

功能最低版本说明
基础功能PHP 8.1本文档基准版本
只读属性PHP 8.1public readonly 修饰符
枚举类型PHP 8.1enum 类型和 match 表达式
FiberPHP 8.1协程/轻量级并发
命名参数PHP 8.0foo(arg_name: value)
联合类型PHP 8.0`int
Null 安全运算符PHP 8.0$obj?->method()
析构器 promotionPHP 8.0__construct(public $x)
php
<?php
declare(strict_types=1);

// 版本兼容性检测
function ensureVersion(string $minVersion): void
{
    if (version_compare(PHP_VERSION, $minVersion, '<')) {
        throw new RuntimeException(
            sprintf('需要 PHP %s+, 当前版本: %s', $minVersion, PHP_VERSION)
        );
    }
}

ensureVersion('8.1.0');

参考链接