array_intersect()比较值,array_intersect_assoc()同时比较键和值。那如果只想比较键名,不关心值是什么?
array_intersect_key()就是干这个的——比较两个或多个数组的键名,返回第一个数组中存在于其他所有数组的那些键名对应的条目。这个函数从PHP 5.1开始可用。
语法格式
array array_intersect_key(array $array1, array $array2 [, array $... ]): array
参数说明:
| 参数 | 说明 | 必填? |
|---|---|---|
| array1 | 基准数组 | 必填 |
| array2 | 第一个对比数组 | 必填 |
| array3... | 更多对比数组 | 可选 |
返回值: 返回一个数组,包含所有在array1中存在并且在其他所有数组中也存在的键名对应的条目。
三种交集函数的区别
| 函数 | 比较内容 | 匹配条件 |
|---|---|---|
| array_intersect() | 只比较值 | 值相等就行 |
| array_intersect_key() | 只比较键名 | 键名相等就行 |
| array_intersect_assoc() | 键名+值 | 键名和值都必须相等 |
示例1:基础用法
<?php
$config_default = [
"host" => "localhost",
"port" => 3306,
"username" => "root",
"timeout" => 30
];
$config_user = [
"host" => "192.168.1.100",
"port" => 3307,
"charset" => "utf8"
];
$common_keys = array_intersect_key($config_default, $config_user);
print_r($common_keys);
?>
输出:
Array
(
[host] => localhost
[port] => 3306
)
注意:只比较键名,不比较值。host和port在两个数组中都存在(即使值不同),所以被返回。返回值用的是第一个数组的值(localhost和3306)。
示例2:多个数组比较
<?php
$schema_v1 = [
"id" => "int",
"name" => "string",
"age" => "int",
"email" => "string"
];
$schema_v2 = [
"id" => "int",
"name" => "string",
"phone" => "string"
];
$schema_v3 = [
"id" => "int",
"name" => "string",
"address" => "string"
];
$common_fields = array_intersect_key($schema_v1, $schema_v2, $schema_v3);
print_r($common_fields);
?>
输出:
Array
(
[id] => int
[name] => string
)
只有id和name三个版本都有。age只在v1有,email只在v1有,phone只在v2有,address只在v3有。
示例3:索引数组的键名比较
<?php
$weekdays = ["周一", "周二", "周三", "周四", "周五"];
$workdays = ["周一", "周三", "周五"];
$common = array_intersect_key($weekdays, $workdays);
print_r($common);
?>
输出:
Array
(
[0] => 周一
[2] => 周三
[4] => 周五
)
索引数组的键名是数字下标。$weekdays的下标0、2、4在$workdays中存在(因为$workdays的下标0是"周一"、下标1是"周三"、下标2是"周五"),所以被返回。注意不是按值匹配的——如果位置错乱了,结果就不一样了。
个人经验分享
-
什么时候用array_intersect_key?
-
找出多个数组的共同字段(结构对比)
-
API版本兼容性检查:新版本是否包含旧版本的所有字段
-
数据库表结构对比:找出共同列
-
配置项合并前的交集分析
-
-
和array_intersect()的典型对比
$a = ["apple" => 1, "banana" => 2, "cherry" => 3]; $b = ["apple" => 100, "banana" => 200, "date" => 400]; // 只比较值:1和2不在b的值里(b的值是100、200、400) print_r(array_intersect($a, $b)); // 空数组 // 只比较键名:apple和banana在b的键名中 print_r(array_intersect_key($a, $b)); // ["apple"=>1, "banana"=>2] -
性能方面
array_intersect_key()只比较键名,通常比array_intersect_assoc()快,因为不需要比较值。 -
常见组合用法
// 从一个大数组中只提取指定键名的字段(类似于白名单) $allowed_keys = ["name", "email", "phone"]; $user_data = ["id" => 1, "name" => "张伟", "email" => "test@test.com", "phone" => "1380000", "role" => "admin"]; $filtered = array_intersect_key($user_data, array_flip($allowed_keys)); // array_flip把白名单变成键名数组,然后用intersect_key过滤
示例4:代码号学习编程场景
<?php
// 场景:多个数据源的学生信息,找出公共字段
$source_db = [
"student_id" => "varchar(20)",
"name" => "varchar(50)",
"age" => "int",
"class" => "varchar(20)",
"score" => "int"
];
$source_api = [
"student_id" => "string",
"name" => "string",
"grade" => "int",
"score" => "int"
];
$source_csv = [
"id" => "string",
"student_name" => "string",
"score" => "int"
];
// 找出三个数据源都有的字段
$common_keys = array_intersect_key($source_db, $source_api, $source_csv);
print_r($common_keys);
// 找出只在数据库表中存在的字段
$db_only = array_diff_key($source_db, $source_api, $source_csv);
echo "\n只在数据库中的字段:\n";
print_r($db_only);
?>
输出:
Array
(
[score] => int
)
只在数据库中的字段:
Array
(
[student_id] => varchar(20)
[name] => varchar(50)
[age] => int
[class] => varchar(20)
)
示例5:白名单过滤(配合array_flip)
<?php
// 用户提交的数据(可能包含恶意字段)
$submitted = [
"username" => "代码号001",
"email" => "user@test.com",
"role" => "admin",
"is_deleted" => 1,
"password" => "123456"
];
// 允许更新的字段白名单
$allowed_fields = ["username", "email"];
// 方法1:用array_intersect_key + array_flip
$safe_data = array_intersect_key($submitted, array_flip($allowed_fields));
// 方法2:手动循环(结果一样)
$safe_data2 = [];
foreach ($allowed_fields as $field) {
if (isset($submitted[$field])) {
$safe_data2[$field] = $submitted[$field];
}
}
echo "过滤后的安全数据:\n";
print_r($safe_data);
?>
输出:
过滤后的安全数据:
Array
(
[username] => 代码号001
[email] => user@test.com
)
这是array_intersect_key的一个经典用法:配合array_flip做输入数据的白名单过滤,防止用户提交额外字段。
示例6:数字键名的严格性
<?php
$arr1 = [1 => "apple", "2" => "banana", 3 => "cherry"];
$arr2 = ["1" => "fruit1", 2 => "fruit2", 3 => "fruit3"];
$intersect = array_intersect_key($arr1, $arr2);
print_r($intersect);
?>
输出:
Array
(
[3] => cherry
)
键名比较时,整数1和字符串"1"被认为是不同的。所以1和"2"不匹配,"2"和2也不匹配。只有3和3(都是整数)匹配上了。这是array_intersect_key的一个容易踩的坑。
本节课程知识要点
-
array_intersect_key()返回第一个数组中存在于其他所有数组的键名对应的条目 -
只比较键名,不比较值
-
和
array_intersect()的区别:后者只比较值 -
和
array_intersect_assoc()的区别:后者同时比较键名和值 -
配合
array_flip()可以做白名单过滤 -
数字键名和字符串数字键名会被视为不同
-
从PHP 5.1开始可用