钩子文档

posts_where

💡 云策文档标注

概述

posts_where 过滤器用于修改 WP_Query 查询中的 WHERE 子句,允许开发者根据特定条件限制文章显示。它常与 restrict_manage_posts 结合使用,实现自定义筛选功能。

关键要点

  • 过滤器参数包括 $where(WHERE 子句字符串)和 $query(WP_Query 实例引用)。
  • 可用于限制文章在网站不同区域的显示,例如基于作者或分类条件。
  • 某些函数(如 get_posts)默认抑制过滤器,需设置 suppress_filters 为 false 以启用 posts_where 过滤。
  • 注意标准文章类型(如 post、page、attachment)的 post_type 查询变量可能未设置,需通过 WP_Query 方法(如 is_page())检测。

代码示例

add_filter( 'posts_where', 'posts_where' );
function posts_where( $where ) {
    if( is_admin() ) {
        global $wpdb;
        if ( isset( $_GET['author_restrict_posts'] ) && !empty( $_GET['author_restrict_posts'] ) && intval( $_GET['author_restrict_posts'] ) != 0 ) {
            $author = intval( $_GET['author_restrict_posts'] );
            $where .= " AND ID IN (SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id=$author )";
        }
    }
    return $where;
}

注意事项

  • 在 taxonomy archive 查询中,post_type 可能未设置,这是一个已知 bug。
  • 使用过滤器时,确保查询函数未抑制过滤器,否则过滤效果可能不生效。

📄 原文内容

Filters the WHERE clause of the query.

Parameters

$wherestring
The WHERE clause of the query.
$queryWP_Query
The WP_Query instance (passed by reference).

More Information

  • This filter applies to the posts where clause and allows you to restrict which posts will show up in various areas of the site. Combined with restrict_manage_posts it allows you to only show posts matching specific conditions.

    Here is an example to match the restrict_manage_posts example:

add_filter( 'posts_where' , 'posts_where' );

function posts_where( $where ) {

if( is_admin() ) {
global $wpdb;

if ( isset( $_GET['author_restrict_posts'] ) && !empty( $_GET['author_restrict_posts'] ) && intval( $_GET['author_restrict_posts'] ) != 0 ) {
$author = intval( $_GET['author_restrict_posts'] );

$where .= " AND ID IN (SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id=$author )";
}
}
return $where;
}

Depending on setup, if we had a custom post type of type ‘book’ with a taxonomy (category style) of type ‘author’, this filter would allow us to only show books written by a specific author.

  • Certain functions which retrieve posts do not run filters, so the posts_where filter functions you attach will not modify the query. To overcome this, set suppress_filters to false in the argument array passed to the function. The following code sample illustrates this.

  • //some function that modifies the query
    function useless_condition ( $where ) { return $where . ' AND 1=1 '; }
    
    //attach your function to the posts_where filter
    add_filter( 'posts_where' , 'useless_condition' );
    
    //get posts AND make sure filters are NOT suppressed
    $posts = get_posts( array( 'suppress_filters' => FALSE ) );

    Source

    $where = apply_filters_ref_array( 'posts_where', array( $where, &$this ) );
    

    Changelog

    Version Description
    1.5.0 Introduced.

    User Contributed Notes

    1. Skip to note 2 content

      Please note that the post_type query variable is not set for standard types (page, post and attachment, see WP_QUery class file line 2396 on trac), only for custom post types, so this is how you can test for each type,

          add_filter( 'posts_where' , 'posts_where', 10, 2);
          function posts_where( $args, $wp_query_obj ) {
            $type = $wp_query_obj->query_vars['post_type'];
            switch(true){
              case 'any'==$type: //query any type (see codex for more details).
                break;
              case !empty($type) && is_array($type):
                //multiple post types define
                break;
              case !empty($type):
                //post type is a custom post.
                break;
              case $wp_query_obj->is_attachment():
                //post type is empty but is a media.
                $type='attachment';
                break;
              case $wp_query_obj->is_page():
                //post type is empty but is a page.
                $type='page';
                break;
              default:
                //post type is empty and not an attachment nor a page, so is a post.
                $type='post';
                break;
            }
            return $where;
          }