场景:按部门拆分 Repeater 行
很多 Bricks 用户会在页面上用 ACF Repeater 存“团队成员”:一个 Repeater 字段,每个成员一行,行里有姓名(text)和部门(radio/select)等子字段。问题来了——需求是“按部门分开显示”,比如工程部一栏、人事部一栏。
社区里的经典疑问是:要不要干脆把数据迁到 CPT 再用三个循环?其实不必。Repeater 行本来就在查询循环里逐行输出,我们只需要在结果层面把行筛一遍。本文演示怎么用 Bricks 官方的 bricks/query/run 过滤器,把 ACF Repeater 查询循环的结果按子字段值过滤,一行代码不写进构建器,全在 functions.php 里完成。
Step 1:搭建字段组与查询循环
-
ACF 字段组挂在 Page 上:Repeater 字段
team_members,子字段name(text)和department(radio,选项 Engineering / HR / Design 等)。 -
在页面里填好成员数据。
-
用 Bricks 编辑该页面,在 Block 上启用查询循环,查询类型选择你的 ACF Repeater 字段。
-
循环里放 Basic Text 输出
{acf_name}和{acf_department},前端能看到全部成员。
此时所有行都会显示。接下来做筛选。
Step 2:bricks/query/run 按子字段筛选
把下面代码加到子主题的 functions.php(去掉开头的 PHP 标签)或代码片段插件里:
add_filter( 'bricks/query/run', function( $results, $query, $query_type ) {
// 只处理 ACF Repeater 类型的查询
if ( $query_type !== 'acf-repeater' || empty( $results ) ) {
return $results;
}
$department = 'Engineering'; // 改成你要筛的部门
return array_values( array_filter( $results, function( $row ) use ( $department ) {
return isset( $row['department'] ) && $row['department'] === $department;
} ) );
}, 10, 3 );
原理拆解:
-
bricks/query/run是 Bricks 查询系统的总出口过滤器,三个参数依次是$results(查询结果)、$query(查询配置数组)、$query_type(查询类型字符串)。任何查询类型的结果都能在这里拦截修改; -
acf-repeater是 Bricks 内置的 ACF Repeater 查询类型标识。此时$results里每个元素对应 Repeater 的一行,是以子字段名为键的关联数组,所以直接取$row['department']就能比对; -
array_filter按条件过滤行,array_values重新索引数组,防止 JSON/循环输出出现键位空洞; -
返回的新数组交给 Bricks 继续渲染,前端就只剩 Engineering 部门的人了。
这个方法对任何“值存字符串”的子字段类型都适用:text、radio、select 都行。想筛多种值就把 $department 换成数组,用 in_array 判断。
相关阅读:
按元素 ID 区分多个循环
需求是三栏各显示一个部门,而过滤器是全局的——一个 $department 怎么服务三个循环?答案是:一个函数里做多套规则,用元素 ID 区分。Bricks 的 $query 数组里带 element_id,就是构建器里每个元素唯一的 brxe-xxxx ID:
add_filter( 'bricks/query/run', function( $results, $query, $query_type ) {
if ( $query_type !== 'acf-repeater' || empty( $results ) ) {
return $results;
}
// 元素 ID => 要保留的部门
$rules = [
'brxe-engineering' => 'Engineering',
'brxe-hr' => 'HR',
'brxe-design' => 'Design',
];
$element_id = isset( $query['element_id'] ) ? $query['element_id'] : '';
if ( ! isset( $rules[ $element_id ] ) ) {
return $results;
}
$department = $rules[ $element_id ];
return array_values( array_filter( $results, function( $row ) use ( $department ) {
return isset( $row['department'] ) && $row['department'] === $department;
} ) );
}, 10, 3 );
元素 ID 怎么拿:在构建器里选中 Block,检查器里能看到元素 ID(形如 brxe-ab12cd);也可以先在查询设置里把查询类型选好,保存后看页面 HTML 源码中该循环容器的 class。
常见误区
- 过滤器是全局的:
bricks/query/run一挂上,对所有 ACF Repeater 查询都生效。务必先判断$query_type === 'acf-repeater',否则会误伤其它查询——多循环场景再用$query['element_id']分流。 - 忘了
array_values:array_filter会保留原键,键位空洞可能引发 JSON 或循环输出的诡异问题,重新索引这一步别省。 - 筛选条件写死在代码里:部门值变了要改代码。想在前端控制,可以改成从字段、选项或 URL 参数读取,按需扩展(具体写法以官方文档为准)。
小结:ACF Repeater 行筛选 = bricks/query/run + array_filter。记住三个关键点:只在 $query_type === 'acf-repeater' 时动手(避免误伤其他查询);$results 的行是关联数组,直接用子字段名取值;多循环场景靠 $query['element_id'] 分流。这个模式同样可以用于按布尔子字段、按数字范围筛行,思路完全一致——拿到行数组,怎么筛都行。
常见问题(FAQ)
Q:这个过滤器会影响页面上的其他查询吗?
A:会,它是全局的。所以代码里先判断 $query_type === 'acf-repeater',只处理 Repeater 查询,其它类型原样返回。
Q:三个循环各筛一个部门怎么做?
A:用 $query['element_id'] 区分:构建器里每个元素有唯一的 brxe-xxxx ID,在函数里按 ID 对应不同的筛选规则。
Q:元素 ID 怎么获取?
A:在构建器里选中 Block,检查器里能看到元素 ID(形如 brxe-ab12cd),或看页面 HTML 中该循环容器的 class。
Q:布尔、数字子字段能筛吗? A:能。行的值是「子字段名 => 值」的关联数组,布尔比真值、数字比大小都行,思路完全一致。
Q:需要改字段结构或迁移数据吗? A:不用,筛选发生在查询结果层面,字段结构和数据原样不动。
延伸阅读
- 想要现成外贸独立站模板与建站实战?看 铲子铺 chanzipu 的外贸建站教程(同用 Bricks,从零搭出能收询盘的站)
- 相关阅读:Bricks Setup Guide
延伸阅读
Bricks 按 ACF Repeater 子字段排序行
教程:Bricks 按 ACF Repeater 子字段排序行——acf 附完整代码可直接复用,适合外贸独立站与 WordPress 开发者。
tutorialBricks Query Loop:精选文章置顶且不重复(PHP 查询实现)
教程:Bricks Query Loop:精选文章置顶且不重复(PHP 查询实现)——query loop 附完整代码可直接复用,适合外贸独立站与 WordPress 开发者。
tutorialACF Relationship 字段 + Bricks 查询循环:显示关联文章
教程:ACF Relationship 字段 + Bricks 查询循环:显示关联文章——acf 附完整代码可直接复用,适合外贸独立站与 WordPress 开发者。
tutorialBricks 让元素输出 N 次(N = 自定义字段值):Array 查询类型实战
教程:Bricks 让元素输出 N 次(N = 自定义字段值):Array 查询类型实战——query loop 附完整代码可直接复用,适合外贸独立站与 WordPress 开发者。
