求助: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
相关产品推荐
相关产品推荐

