You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:WordPress前端仅显示positions自定义文章类型唯一内容

问题描述

我正在尝试展示名为「positions」的自定义文章类型,目前存在的问题是该类型下有多篇文章的标题、分类法(job_type、city)、自定义字段(company)完全或部分重复。我希望实现以下过滤规则:

  • 当标题与所有分类法、自定义字段数据均相同时,仅显示一篇文章;
  • 若标题与任一分类法或自定义字段匹配且存在多篇重复内容时,也仅保留一篇。

我尝试使用以下代码,但前端未产生任何变化。我当前使用Bricks Builder作为页面构建器,寻求合适的WordPress钩子或过滤器来实现文章过滤。

function filter_duplicate_posts( $query ) {
    // 检查文章类型是否为"pay-trackers"且是否为主查询(此处原代码写错,目标类型应为positions)
    if ( $query->is_main_query() && $query->get( 'post_type' ) == 'positions' ) {
        // 获取所有已发布文章的ID
        $titles = get_posts( array(
            'post_type' => 'positions',
            'post_status' => 'publish',
            'fields' => 'ids',
            'posts_per_page' => -1
        ) );
 
        // 从数组中移除重复的ID(无意义,因为每个文章ID都是唯一的)
        $titles = array_unique( $titles );
 
        // 设置post__not_in参数排除这些文章(会导致所有文章被排除)
        $query->set( 'post__not_in', $titles );
    }
}
add_action( 'pre_get_posts', 'filter_duplicate_posts' );
问题分析与解决方案

你的代码存在三个核心问题:一是逻辑错误,用ID数组去重毫无意义,且post__not_in设置会排除所有文章;二是未覆盖分类法和自定义字段的去重逻辑;三是Bricks Builder可能不依赖主查询渲染列表,导致pre_get_posts钩子未触发。以下是两种适配需求的可行方案:

方案一:SQL层面分组去重(适合主查询场景)

通过posts_distinct和posts_groupby钩子,在SQL层面按标题、自定义字段、分类法组合分组,实现精准去重:

function remove_duplicate_positions( $query ) {
    // 针对前台的positions类型查询生效
    if ( ! is_admin() && $query->get( 'post_type' ) === 'positions' ) {
        add_filter( 'posts_distinct', '__return_true' );
        add_filter( 'posts_groupby', function( $groupby ) {
            global $wpdb;
            
            // 按标题、company字段、job_type分类、city分类分组(假设每个文章对应单个分类术语)
            $groupby = "
                {$wpdb->posts}.post_title,
                (SELECT meta_value FROM {$wpdb->postmeta} WHERE post_id = {$wpdb->posts}.ID AND meta_key = 'company' LIMIT 1),
                (SELECT term_id FROM {$wpdb->term_relationships} tr JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id = {$wpdb->posts}.ID AND tt.taxonomy = 'job_type' LIMIT 1),
                (SELECT term_id FROM {$wpdb->term_relationships} tr JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id = {$wpdb->posts}.ID AND tt.taxonomy = 'city' LIMIT 1)
            ";
            return $groupby;
        });
    }
}
add_action( 'pre_get_posts', 'remove_duplicate_positions' );

注意:如果文章对应多个分类术语,需调整SQL逻辑适配多值场景。

方案二:Bricks查询结果后过滤(适配页面构建器自定义查询)

如果Bricks使用自定义查询而非主查询,直接用bricks/posts/query_result钩子处理返回的文章数组:

function filter_bricks_positions_duplicates( $posts, $query ) {
    // 仅处理positions类型的查询
    if ( $query->get( 'post_type' ) !== 'positions' ) {
        return $posts;
    }

    $seen_keys = array();
    $unique_posts = array();

    foreach ( $posts as $post ) {
        // 获取自定义字段值
        $company = get_post_meta( $post->ID, 'company', true );
        // 获取分类术语ID(取第一个)
        $job_type_terms = wp_get_post_terms( $post->ID, 'job_type', array( 'fields' => 'ids' ) );
        $job_type = ! empty( $job_type_terms ) ? $job_type_terms[0] : '';
        $city_terms = wp_get_post_terms( $post->ID, 'city', array( 'fields' => 'ids' ) );
        $city = ! empty( $city_terms ) ? $city_terms[0] : '';

        // 生成唯一标识:标题+company+job_type+city(可按需调整组合规则)
        $unique_key = md5( $post->post_title . $company . $job_type . $city );

        // 未出现过的标识则保留文章
        if ( ! isset( $seen_keys[$unique_key] ) ) {
            $seen_keys[$unique_key] = true;
            $unique_posts[] = $post;
        }
    }

    return $unique_posts;
}
add_filter( 'bricks/posts/query_result', 'filter_bricks_positions_duplicates', 10, 2 );

此方案兼容性更强,直接处理Bricks返回的结果,无需依赖主查询判断。

额外提示

  • 若需实现「任一字段匹配即去重」,可修改$unique_key的生成逻辑(比如仅保留标题,或标题+company);
  • 测试前请清空WordPress缓存和Bricks页面缓存,避免旧结果干扰。

内容的提问来源于stack exchange,提问作者Ilham Mohomed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 08:50:19