WordPress posts_where Hook: Customize the Where Clause of WP_Query

By | September 21, 2020

WordPress WP_Query class allows us to query posts by some conditions.

Here is the tutorial:

WordPress WP_Query Class: Query Posts by Condition

Meanwhile, if you want to add or change some conditions before querying posts, you can use pre_get_posts.

Here is the tutorial:

WordPress pre_get_posts: Customize the Query Parameter of WP_Query

However, pre_get_posts only allows you to change the query parameters in WP_Query query arguments.

A Full List of WordPress WP_Query Query Arguments ($args)

If you want to add some custom query paramters not in WP_Query query arguments, how to do?

In this tutorial, we will use wordpress posts_where hook to implement.

What is posts_where hook?

posts_where hook can allow us to change or modify the sql where clause before executed by WP_Query.

How to use posts_where hook?

The basic usage of posts_where hook is:

add_filter('posts_where', function ($where, $query) {
    // get query parameters
    $post_title = $query->query['post_title'];
    
    return $where;
}, 10, 2);

where $where is the sql where clause that will be executed in WP_Query.

$query is the query parameters will be used in WP_Query. $where is created based on $query.

In this tutorial, we will get the related posts of a post based on post title with a fulltext search.

We will add a match against query in $where.

$where .= " and MATCH ({$wpdb->prefix}posts.post_title) AGAINST('".$keyx."' IN NATURAL LANGUAGE MODE)";

The full code is below:

$current_object = get_queried_object(); // it is a post object
$related_args['post__not_in'] = array( absint( $current_id ) );
$related_args['post_title'] = $current_object->post_title;
		
add_filter('posts_where', function ($where, $query) {
    $post_title = $query->query['post_title'];
    if(isset($query->query['post_title']) and $query->query['post_title'] !=""){
        global $wpdb;
	$keyx =  esc_sql($post_title);
	$where .= " and MATCH ({$wpdb->prefix}posts.post_title) AGAINST('".$keyx."' IN NATURAL LANGUAGE MODE)";
    }
    //echo $where;
    return $where;
}, 10, 2);
$related_posts = new WP_Query( $related_args );

Run this code, you will find we have added match against query in WP_Query.

Leave a Reply