$query->set in pre_get_posts is unintentionally affecting the backend

So, I have a custom post type, ‘properties’.

I’m using archive-properties.php, and need to set some parameters on the $query.

I don’t want to use new WP_Query since I ran into some issues where a pagination plugin was trying to paginate the $query that already existed since we were on an archive page, if that makes any sense.

So now my problem is, if I set posts_per_page to 2 for example, and login to the backend, its only showing 2 posts.

So I need this to change the query on the frontend, but not the backend. I don’t know what to include in the if statement.

function set_query_parameters($query) {

    if( is_main_query() && is_post_type_archive( 'properties' ) && !$_SESSION  ) {           
        $query->set('posts_per_page', 12);
        $query->set('orderby', array(
            'date' => 'DESC',
        ));
    }
    return $query;
}

add_action( 'pre_get_posts', 'set_query_parameters' );

1
1

In regards to your decision not to use WP_Query, pre_get_posts is actually an excellent choice to make, rather than creating a new instance of WP_Query. In fact, pre_get_posts is exactly what you should be using when you want to change the main query. Rather than executing a separate query on each page load, it modifies the main query’s parameters before it executes. Much more efficient!

You’re almost there. You just need to add !is_admin() to your if statement. You also should specifically call is_main_query() on the $query object passed to your function.

With these two changes your if statement would now read:

if( !is_admin() && $query->is_main_query() && is_post_type_archive( 'properties' ) && !$_SESSION  ) {

It’s also worth noting that you don’t need to return a value to a WordPress action – as opposed to a filter. With pre_get_posts, the argument is passed by reference so any changes you make to your $query variable will take effect automatically.

Leave a Comment