How to make a WP_Query search with custom post types?

I’ve registered a custom post type called “node”.

When I create a basic WP_Query to get posts of that type, it works just fine. Example:

Read More
$args = array(  
'post_status' => 'publish',
'post_type' => 'node');

$query = new WP_Query($args);       

This will get all published posts of type “node”.

However, as soon as I combine this with a search, nothing is returned. Example:

$args = array(  
'post_status' => 'publish',
'post_type' => 'node',
's' => 'My search term');

$query = new WP_Query($args);

This will get nothing, although it should get several posts of type ‘node’ that contain ‘My search term’.

As far as I can see, the post types are automatically set to “post” and “page” as soon as I include the “s” parameter in $args. If I print out a var_dump of $query, it shows the following:

Without “s”:

object(WP_Query)
  public 'query' => 
    array (size=2)
      'post_status' => string 'publish' (length=7)
      'post_type' => string 'node' (length=4)
  public 'query_vars' => 
    array (size=63)
      'post_status' => string 'publish' (length=7)
      'post_type' => string 'node' (length=4)
...

With “s”:

object(WP_Query)
  public 'query' => 
    array (size=2)
      'post_status' => string 'publish' (length=7)
      's' => string 'My search term' (length=14)
      'post_type' => string 'node' (length=4)
  public 'query_vars' => 
    array (size=66)
      'post_status' => string 'publish' (length=7)
      's' => string 'My search term' (length=14)
      'post_type' => 
        array (size=2)
          0 => string 'post' (length=4)
          1 => string 'page' (length=4)
...

So WordPress seems to override the post types as soon as a search is involved.

How can I fix that?

Related posts

4 comments

  1. You are right, I tried it in a clean WordPress install and it works.

    Seems like one of the plugins I use in my environment is hooking itself in one of the pre-query events.

    Thanks!

  2. On a stock WordPress installation, WP_Query will default to post_type = 'post'.

    Consider this simple example:

    $args = array(
      "posts_per_page"=>5,
      "ignore_sticky_posts"=>true
    );
    
    $itposts = new WP_Query( $args );
    

    It will result in the following query to be executed:

    SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 5

    THE BEST SOLUTION

    The solution is to add a post_type argument set to 'any'. This way WordPress will automaticaly search among all types except revisions and types with exclude_from_search set to true. Problem, by default, attachments are not excluded from search. As long as you don’t have a post_status argument set to 'inherit', you should not be annoyed because attachments always have post_status set to 'inherit'.

    This way the query will change to:

    SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type IN ('post', 'page', 'attachment') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 5

    If needed, you can exclude attachments from search by using this code:

    add_action('init', 'exclude_attachments_from_search');
    
    function exclude_attachments_from_search() {
      global $wp_post_types;
    
      $wp_post_types['attachment']->exclude_from_search = true;
    }
    
  3. I’ve just stepped in this, and such solution worked for me:

    instead of 'post_type' => 'node' try 'post_type' => ['node']

  4. I know this is a really old question but I came across this because I had the same problem. I can’t comment because of reputation, but I want to help people like @Stefano so you don’t have to go through all your plugins and check which one causes the change to the query.

    For me it was a plugin called “Custom Search by BestWebSoft“. But it wasn’t the plugins fault, I just hadn’t ticked the box for my custom post type in its settings.

Comments are closed.