WordPress

How to override a WordPress Result set.

Reading Time: 2 minutes

Add the action to the functions.php file

The first thing you’ll need to do is add the action ‘pre_get_posts’ and your custom function name which will be used to override the query.

add_action('pre_get_posts', 'geekcafe_override_query_results');

Limit the number of post per page

In the following examples, I’m going to make the override simple and just limit the number of posts per page. This is just an example, so you can see the flow. You can easily change the filter to suit your needs.

I’ll also several scenarios that limit the scope of where the action will take place. Again these are just examples and you can easily change them to suit your needs.

Scenario 1: All Post (front end & admin)

function geekcafe_override_query_results( $query ) {
    $query->set('posts_per_page', '1');
}

Scenario 2: All Posts (front end only)

function geekcafe_override_query_results( $query ) {
   if ( !is_admin() ) {    
       $query->set('posts_per_page', '1');
   }
}

The is_admin() function always makes me stop and think about what it’s true nature is.

From the moment I saw the function name, I interpreted it to be if the logged-in user is an admin(); however, that’s not it’s behavior, instead, it means – are we in the admin UI. It returns true if we are in the admin UI otherwise it is false.

Scenario 3: All Front End Post of a specific type

function geekcafe_override_query_results( $query ) {
   if ( !is_admin() AND get_post_type() == 'event' ) {    
       $query->set('posts_per_page', '1');
   }
}

Scenario 4: All Front End Posts of a Specific Type and Not a Custom Query

function geekcafe_override_query_results( $query ) {
   if ( !is_admin() AND get_post_type() == 'event' AND $query->is_main_query() ) {    
       $query->set('posts_per_page', '1');
   }
}

The condition above checks the query to see if it’s the default WP query for the given request and hasn’t been overridden via WP_Query

Setting multiple fields

The examples above simply do a set on a single field, but let’s say we wanted to override more. In this case, we add more set(s).

Add additional fields

 $query->set('orderby' , 'title');
 $query->set('order' ,'ASC');

Custom Fields

In the example below, we’ll add a filter on a custom field.

In this example, we’ll only show pages that haven’t expired yet.

// get today's date
$today = date('Ymd);

// show any post that haven't expire
// the expire_date field needs to be less than or equal to today
$query->set('meta_query',  array (
        'key' => 'expire_date',       // column or custom key
        'compare' => '<=',           // operator =, !=, <=, =>    
        'value' => $today,           // today's date
        'type' => 'numeric'         // treat it as numeric comparrison
      )
);

Add some additional complexity

The example above assumes that all of your posts have set the custom post type’s custom field. But what if it’s not required or if it’s a new custom field?

In this case, we need to account for missing custom field data or null custom fields.

// get today's date
$today = date('Ymd);

// show any post that haven't expire
// the expire_date field needs to be less than or equal to today
$query->set('meta_query',  array (
        'relation' => 'OR',
        array (
            'key' => 'expire_date',       
             'compare' => '<=',           
        'value' => $today,           
        'type' => 'numeric'        
      )
);

Let me know what your favorite use case is!