在首页、落地页或其他非归档模板中查询自定义文章,应创建独立的 WP_Query。不要使用 query_posts() 覆盖主查询,也不要把 ACF 字段名和值直接拼接成 SQL。
假设要显示属于多个产品分类、并且 ACF 状态字段为 featured 的产品:
<?php
$category_ids = array( 12, 18, 27 );
$query = new WP_Query(
array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => 12,
'no_found_rows' => true,
'ignore_sticky_posts' => true,
'orderby' => 'date',
'order' => 'DESC',
'tax_query' => array(
array(
'taxonomy' => 'product_category',
'field' => 'term_id',
'terms' => array_map(
'absint',
$category_ids
),
'operator' => 'IN',
),
),
'meta_query' => array(
array(
'key' => 'product_status',
'value' => 'featured',
'compare' => '=',
),
),
)
);
if ( $query->have_posts() ) {
echo '<div class="product-grid">';
while ( $query->have_posts() ) {
$query->the_post();
get_template_part(
'template-parts/content',
'product-card'
);
}
echo '</div>';
} else {
echo '<p>暂无推荐产品。</p>';
}
wp_reset_postdata();
多个分类的关系
上面 terms + IN 的含义是“命中这些分类中的任意一个”。如果必须同时属于多个 term,可为每个 term 建立一个 tax_query 子句并设 relation => AND,但查询成本会更高,应结合真实数据量测试。
若分类由页面的 ACF Taxonomy 字段选择,建议让字段返回 term ID,再过滤:
$category_ids = array_values(
array_filter(
array_map(
'absint',
(array) get_field(
'featured_categories',
get_the_ID(),
false
)
)
)
);
空数组时要明确产品规则:显示空态、跳过模块,还是使用默认分类。不要让空 tax_query 意外返回所有产品。
ACF 字段查询的成本
WordPress 的 meta_query 最终查询 postmeta。在数据量较大、组合筛选很多时,它可能成为性能瓶颈。高频过滤字段可以考虑:
- 用 taxonomy 表达有限枚举状态。
- 使用专用数据表与明确索引。
- 缓存稳定的推荐结果。
- 限制后台可选项,避免无限组合查询。
ACF 适合内容编辑体验,但字段存在哪里、如何查询仍由 WordPress 数据模型决定。
主查询何时用 pre_get_posts
如果你修改的就是当前归档页或搜索页的主列表,在 pre_get_posts 中判断 ! is_admin()、$query->is_main_query() 和具体页面条件。独立首页模块才使用新的 WP_Query。