在 WordPress 中如何查找数组元素?从 PHP 的 array_find 到 wpjam_find
在 PHP 8.4 之前,如果你想在数组里找到第一个满足条件的元素,要么写个 foreach 加 break:
$found = null;
foreach($arr as $v){
if($v > 10){
$found = $v;
break;
}
}
要么先 array_filter 再取第一个:
$filtered = array_filter($arr, fn($v) => $v > 10);
$found = reset($filtered);
前者啰嗦,后者不短路还会额外分配数组,性能和优雅度都不够。如果想找数字索引,还得再套一层:
$index = array_search($key, array_keys($arr));
代码越写越长,语义越来越模糊。
array_find 和 array_find_key
到了 PHP 8.4,终于补上了这两块拼图:
// 找第一个满足条件的值
$value = array_find($arr, fn($v) => $v > 10);
// 找第一个满足条件的键
$key = array_find_key($arr, fn($v) => $v > 10);
PHP 7 用户注意:WPJAM Basic 内置了这两个函数的 polyfill,在 PHP 7 及以上环境下也能正常使用。
它们都支持“命中即停”(短路),性能确实比老旧的 array_filter 强得多。但实际在项目里写代码时,你会发现原生函数只解决了 80% 的基础操作,剩下 20% 的复合场景依然写得很别扭:
原生函数没解决的三个问题
问题 1:想找“数字索引”还得折腾:
$key = array_find_key($arr, $cb);
$index = array_search($key, array_keys($arr));
array_find_key 拿到的是键(Key),如果想要真正的数字索引(Index),得再套一步 array_search。不仅两步走,要是没找到还容易踩到 false 的类型坑。
问题 2:只支持回调,不支持条件查找
$post = array_find($posts, fn($p) => $p['status'] === 'publish' && $p['type'] === 'post');
如果想按关联数组当条件查找(比如['status'=>'publish', 'type'=>'post']),还得手写闭包和 wpjam_matches,外层包得严严实实,噪音极大。
$post = array_find($posts, fn($p) => wpjam_matches($p, ['status'=>'publish', 'type'=>'post']));
问题 3:想"边映射边查找",原生完全不支持
最常见的场景:列表里存的是 ID,如果想边映射边查找:
// 想:找到第一个有缩略图的 term
$url = null;
foreach($terms as $term){
if($url = wpjam_get_term_thumbnail_url($term)){
break;
}
}
又回到了 foreach。
PHP 数组查找增强:wpjam_find
为了把这些弯路抹平,我设计了 wpjam_find 函数。它的核心思路很简单:不取代原生,而是补缺。把各种查找场景统一成一个函数,用参数和返回值来灵活控制。
function wpjam_find($arr, $cb, ...$args){
$assoc = wpjam_is_assoc_array($cb);
$output = in_array($args[0] ?? '', ['value', 'key', 'index'], true) ? $args[0] : ($assoc ? 'value' : 'result');
$cb = $assoc ? fn($v)=> wpjam_matches($v, $cb) : $cb;
if($output == 'result'){
foreach($arr as $k => $v){
$v = $cb($v, $k);
if(!is_null($v)){
return $v;
}
}
}else{
$res = wpjam_call('array_find'.($output == 'value' ? '' : '_key'), $arr, $cb);
return $res === null || $output != 'index' ? $res : array_search($res, array_keys($arr), true);
}
}
四种输出模式
通过传入不同的第三个参数,可以轻松切换输出结果:
| 模式 | 返回 | 说明 |
|---|---|---|
value | 元素值 | 原生 |
key | 数组键 | 原生 |
index | 数字索引 | 自动处理严格比较(防止 0 和 '0' 混淆)与 null 安全 |
result | 映射后的结果 | 原生完全没有的全新能力(闭包默认模式) |
前两种是原生的直接转发;在 index 模式 下,函数内部使用 array_search(..., true) 进行了严格比较,彻底避免了 0 和 '0' 搞混带来的误匹配,找不到时也会安全地返回 null。
两种匹配形式
可以给 $cb 传两种内容:
1. 关联数组(语法糖):比如传 ['status' => 'publish'],会自动走 wpjam_matches 匹配。
2. 闭包(Mapper 映射器):当传入闭包时,wpjam_find 默认走 result 模式,它会把闭包当成映射函数,把元素一个个送进去转换,找到非 null 值立刻返回。
result 模式 = 映射后查找
wpjam_find($arr, $mapper)
$mapper:对每个元素先做转换- 返回第一个"映射结果非 null"的值
null= 跳过,其他值(包括0、''、false)= 命中
在 result(映射查找)模式下,它的工作规则极其清晰:只有返回 null 才算没找到/跳过,或者换个说法只要不是 null 就算“命中”!
| mapper 返回 | 结果 |
|---|---|
null | 跳过,继续找下一个 |
0 / '' / false / '0' / [] | 命中,返回该值 |
| 非空值 | 命中,返回该值 |
这条约定非常关键,在很多业务逻辑里,0、''(空字符串)或者 false 都是完全合法的业务结果,不应该被误当作“没找到”而跳过。
// 找第一个存在的配置值
wpjam_find(['enabled', 'disabled'], fn($k) => $config[$k] ?? null)
// 如果 $config['enabled'] = 0,会正确返回 0,而不是继续找 'disabled'
💡 如果确实想把空值当“未命中”跳过怎么办? 非常简单!在闭包映射表达式后面加个
?: null(例如$url ?: null),显式地把它转成null就行了。
四大实战场景对比
场景 1:取第一个存在的查询参数
// 原生:得写 foreach + break
$cat = null;
foreach(['category_id', 'cat_id'] as $key){
if(!is_null($cat = wpjam_param($key))){
break;
}
}
// wpjam_find:一行搞定,短路逻辑完全一致
$cat = wpjam_find(['category_id', 'cat_id'], fn($k) => wpjam_param($k));
场景 2:按关联条件查找
// 原生:手写闭包和 matches,噪音大
$post = array_find($posts, fn($p) => wpjam_matches($p, ['status'=>'publish', 'type'=>'post']));
// wpjam_find:把关联数组当条件直接传,语义一眼就懂
$post = wpjam_find($posts, ['status'=>'publish', 'type'=>'post']);
场景 3:映射后查找(原生做不到)
// 想:找到第一个有缩略图的 term,并直接返回缩略图 URL
$url = wpjam_find($terms, fn($term) => wpjam_get_term_thumbnail_url($term) ?: null);
// 原生必须写 foreach:
$url = null;
foreach($terms as $term){
if($url = wpjam_get_term_thumbnail_url($term)){
break;
}
}
场景 4:安全拿数字索引
// 原生:两步走,还要手写防坑逻辑
$key = array_find_key($arr, $cb);
$index = $key !== null ? array_search($key, array_keys($arr), true) : null;
// wpjam_find:指定 'index' 模式,一步到位
$index = wpjam_find($arr, $cb, 'index');
总结:一句话搞懂 wpjam_find
简单查找:直接用 PHP 8.4 原生的 array_find 和 array_find_key,干净利落,只有到了复合场景,才需要用 wpjam_find。
wpjam_find 的核心原则很简单:不取代原生,而是补缺:通过关联数组条件,省去手写 wpjam_matches,映射后查找:原生完全缺失的能力。
它通过参数类型自动推断你的意图(传数组查条件,加 'index' 拿索引,传闭包做映射),让你不用记复杂的函数名。
wpjam_find($arr, ['a'=>1]) // 关联数组 → 条件
wpjam_find($arr, fn($v)=> ...) // 闭包 → mapper
wpjam_find($arr, fn($v)=> ..., 'key') // 加模式字符串 → 换输出
还有最重要的一条约定就是“null 才算跳过”,用明确的 null 信号代替模糊的“真值”判断,让 0、''(空字符串)、false 都能作为合法的业务返回值,帮你避开 99% 的类型和逻辑坑。
如果你的项目里也有大量“遍历 + 判断 + 取值”的冗余代码,不妨试试 wpjam_find,大多数情况下,一行就能优雅搞定!
