4

I am trying to customize the search results for a generic search, but only if it's using the search.php template. I have other searches on my site, and I don't want this filter interfering with them. Everything works on the following code, except for is_page_template('search.php').

Once I enter that line of code as a condition, it just reverts to the normal search filtering, because my IF condition is failing. How do I only run my code if we're on the search.php page?

    //Filter the search for only posts and parts
    function SearchFilter($query)
    {
        if ($query->is_search && is_page_template('search')) {
            $query->set('post_type', array('post', 'parts'));
            $query->set('meta_key', 'Manufacturer');
            $query->set('orderby', 'meta_value');
            $query->set('order', 'ASC');
        }
        return $query;
    }

    add_filter('pre_get_posts', 'SearchFilter');
2
  • I suppose is_page_template runs after pre_get_posts. That's why you can't use it yet.
    – Johansson
    Jun 28, 2017 at 14:20
  • 1
    Yes, you're right. Is there another way to check? I'm going to experiment with WP_Query inside the template itself, but it feels kind of silly to have WordPres check the normal way, and then tell it to change its mind and try another way... Jun 28, 2017 at 14:31

2 Answers 2

5

Lets break it down step by step:

if ($query->is_search && is_page_template('search')) {

There are 3 problems here

is_page_template

search.php isn't a page template, that's not how the search template is loaded. So this won't work.

But if it did work, there's a new problem. Functions such as is_page_template etc rely on the main query, but we're in a pre_get_posts filter, you don't know if that query has been set yet, or if you're filtering that query or another.

So we need to:

  • remove the is_page_template check, it doesn't do what you think it does
  • Add an $query->is_main_query() check so the filter doesn't interfere with widgets and other queries

Methods vs member variables

if ($query->is_search

This doesn't work, and should be generating PHP warnings for you. The problem is that is_search is a function/method not a variable, it should be:

if ( $query->is_search() && $query->is_main_query() ) {

But search.php?

WordPress decides which template is loaded based on the main query. If it's the main query, and is_search is true, then search.php will be loaded.

Because of this, WordPress hasn't decided which template to use when your filter happens. In fact, you can make WordPress change which template it loads by modifying the query variables. For example, if you unset all the variables, and tell it to load a single post, you won't get search.php, or an archive at all, you're likely to get single.php instead

What About Search Queries in Page Templates?

is_main_query will be false, so not an issue

3

There is a workaround that might cost you an extra query. However, @Milo once mentioned that WordPress is pretty smart about caching the queries, so this shouldn't be a big deal for you.

You can run the query inside the pre_get_posts and then do some checks. If the situation matched your requirements, then filter the query:

//Filter the search for only posts and parts
function SearchFilter($query)
{
    remove_action('pre_get_posts', 'SearchFilter');
    // Run the query to fetch the results
    $posts = get_posts( $query->query );
    if(!empty($posts)) {
        // Check the template for the first post 
        if( get_page_template_slug( $posts[0]->ID ) == 'YOUR SLUG HERE' ){
            $search_template = true; 
        } else {
            $search_template = false; 
        }
    }
    // Now filter the posts
    if ($query->is_main_query() & $query->is_search && $search_template) {
        $query->set('post_type', array('post', 'parts'));
        $query->set('meta_key', 'Manufacturer');
        $query->set('orderby', 'meta_value');
        $query->set('order', 'ASC');
    }
    return $query;
}

add_action('pre_get_posts', 'SearchFilter');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.