WordPress pre_get_posts多$query->set失效:作者与自定义字段筛选问题
解决WordPress自定义角色文章可见性的OR条件查询问题
你遇到的问题根源是:直接同时设置author和meta条件时,WordPress会生成AND逻辑的SQL查询——要求文章必须同时满足「作者是当前用户」和「parbandeh_masool=2」,这就导致只有同时符合两个条件的文章才会被显示,自然出现无文章的情况。
要实现「自己的文章 + parbandeh_masool=2的文章」的OR逻辑,有两种可靠的解决方法:
方法1:合并文章ID数组(简单易维护)
通过分别获取两类文章的ID,合并后设置查询仅包含这些ID,逻辑直观,适合大多数场景:
add_action('pre_get_posts', 'restrict_invoicer_post_visibility'); function restrict_invoicer_post_visibility($query) { // 仅针对后台文章列表的主查询,且当前用户是invoicer角色 if (!is_admin() || !$query->is_main_query() || $query->get('post_type') !== 'post' || !current_user_can('invoicer')) { return; } $current_user_id = get_current_user_id(); // 获取当前用户的所有文章ID(包含草稿、待审等状态) $user_post_ids = get_posts([ 'author' => $current_user_id, 'post_type' => 'post', 'post_status' => ['publish', 'draft', 'pending', 'future'], 'fields' => 'ids', 'numberposts' => -1 ]); // 获取所有parbandeh_masool值为2的文章ID $masool_post_ids = get_posts([ 'meta_key' => 'parbandeh_masool', 'meta_value' => 2, 'post_type' => 'post', 'post_status' => ['publish', 'draft', 'pending', 'future'], 'fields' => 'ids', 'numberposts' => -1 ]); // 合并并去重ID数组 $allowed_post_ids = array_unique(array_merge($user_post_ids, $masool_post_ids)); // 处理空数组情况,避免显示所有文章 if (empty($allowed_post_ids)) { $allowed_post_ids = [0]; } // 设置查询仅包含允许的文章ID $query->set('post__in', $allowed_post_ids); }
方法2:直接修改SQL查询条件(性能更优)
通过钩子修改SQL的WHERE子句和JOIN语句,直接实现OR逻辑,适合文章数量较多的场景:
add_action('pre_get_posts', 'setup_invoicer_post_query'); function setup_invoicer_post_query($query) { if (is_admin() && $query->is_main_query() && $query->get('post_type') === 'post' && current_user_can('invoicer')) { // 添加WHERE和JOIN钩子 add_filter('posts_where', 'add_invoicer_or_conditions'); add_filter('posts_join', 'add_postmeta_table_join'); } } function add_invoicer_or_conditions($where) { global $wpdb, $current_user; $user_id = $current_user->ID; // 移除默认的author强制条件(如果存在) $where = preg_replace("/\s*AND?\s*\({$wpdb->posts}\.post_author\s*=\s*'{$user_id}'\)/i", "", $where); $where = preg_replace("/^WHERE\s*\({$wpdb->posts}\.post_author\s*=\s*'{$user_id}'\)/i", "WHERE", $where); // 添加OR逻辑条件:作者是当前用户 或者 parbandeh_masool=2 $where .= " AND ({$wpdb->posts}.post_author = '{$user_id}' OR ({$wpdb->postmeta}.meta_key = 'parbandeh_masool' AND {$wpdb->postmeta}.meta_value = '2'))"; return $where; } function add_postmeta_table_join($join) { global $wpdb; // 确保仅连接一次postmeta表 if (strpos($join, $wpdb->postmeta) === false) { $join .= " LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id"; } return $join; }
注意事项
- 替换
invoicer为你的实际自定义角色标识 - 方法1中
post_status的取值需和后台文章列表默认显示的状态一致,确保不会遗漏草稿、待审等状态的文章 - 方法2需注意SQL语句的兼容性,避免和其他查询条件冲突
内容的提问来源于stack exchange,提问作者Ahmad Karimi
相关产品推荐
相关产品推荐

