How to create a custom search for custom post type?

  • I have a search field for the blog posts, but I need an other for a custom post type. How can I create this custom search form with a different search result layout?

  • Here is what I've tried and got a solution with 3 steps. Let's say your custom post type is "products"

    1 . Add Function Code here you can specify the archive-search.php

    function template_chooser($template)   
    {    
      global $wp_query;   
      $post_type = get_query_var('post_type');   
      if( $wp_query->is_search && $post_type == 'products' )   
      {
        return locate_template('archive-search.php');  //  redirect to archive-search.php
      }   
      return $template;   
    }
    add_filter('template_include', 'template_chooser');    
    

    2 . Create search result template for custom post type ( archive-search.php )

            <?php
            /* Template Name: Custom Search */        
            get_header(); ?>             
            <div class="contentarea">
                <div id="content" class="content_right">  
                         <h3>Search Result for : <?php echo "$s"; ?> </h3>       
                         <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>    
                    <div id="post-<?php the_ID(); ?>" class="posts">        
                         <article>        
                        <h4><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h4>        
                        <p><?php the_exerpt(); ?></p>        
                        <p align="right"><a href="<?php the_permalink(); ?>">Read     More</a></p>    
                        <span class="post-meta"> Post By <?php the_author(); ?>    
                         | Date : <?php echo date('j F Y'); ?></span>    
    
                        </article><!-- #post -->    
                    </div>
            <?php endwhile; ?>
        <?php endif; ?>
    
    
    
    
               </div><!-- content -->    
            </div><!-- contentarea -->   
            <?php get_sidebar(); ?>
            <?php get_footer(); ?>
    
    1. Build Search Form
      In this Search Form, the value "products" is hidden and it will search only product posts.

       <div>   
          <h3>Search Products</h3>
          <form role="search" action="<?php echo site_url('/'); ?>" method="get" id="searchform">
          <input type="text" name="s" placeholder="Search Products"/>
          <input type="hidden" name="post_type" value="products" /> <!-- // hidden 'products' value -->
          <input type="submit" alt="Search" value="Search" />
        </form>
       </div>
      

    for more, I would like to link you to here
    http://www.wpbeginner.com/wp-tutorials/how-to-create-advanced-search-form-in-wordpress-for-custom-post-types/

    Tip: when registering the post type, the **publicly_queryable** argument must be set to **true**. If not, the get_query_var('post_type') will never return the post_type value given in the url argument. https://codex.wordpress.org/Function_Reference/register_post_type#Arguments

    Another tip/suggested edit: `get_query_var('post_type')` returned an array (rather than a string) so couldn't be compared directly. Since I'm only searching one post type at a time, I simply changed my `$post_type` var to `$post_type[0]`.

    is there a way to rewrite the url from `http://localhost:3000/?s=cloud%27&post_type=product` to `http://localhost:3000/search/cloud/product`

    the ```search_template``` filter seems to be a more appropriate alternative to ```template_include```

  • Here is what works for me. Not as clean but I couldn't get any of these other answers to work.

    Search form for Custom Post Type:

    <form role="search" method="get" class="search-form" action="<?php echo home_url( '/' ); ?>">
        <label>
            <span class="screen-reader-text"><?php echo _x( 'Search for:', 'label' ) ?></span>
            <input type="search" class="search-field" placeholder="<?php echo esc_attr_x( 'Search …', 'placeholder' ) ?>" value="<?php echo get_search_query() ?>" name="s" title="<?php echo esc_attr_x( 'Search for:', 'label' ) ?>" />
            <input type="hidden" name="post_type" value="book" />
        </label>
        <input type="submit" class="search-submit" value="<?php echo esc_attr_x( 'Search', 'submit button' ) ?>" />
    </form>
    

    In functions.php:

    function searchfilter($query) {
        if ($query->is_search && !is_admin() ) {
            if(isset($_GET['post_type'])) {
                $type = $_GET['post_type'];
                    if($type == 'book') {
                        $query->set('post_type',array('book'));
                    }
            }       
        }
    return $query;
    }
    add_filter('pre_get_posts','searchfilter');
    

    In search.php:

    <?php if (have_posts()) : ?>
    <?php while (have_posts()) : the_post(); ?>
        <?php if(isset($_GET['post_type'])) {
            $type = $_GET['post_type'];
               if($type == 'book') {?>
    
                   /* Format for "book" custom post type */
    
               <?php } else { ?>
    
                   /* Format for custom post types that are not "book,"
                   or you can use elseif to specify a second post type the
                   same way as above. Copy the default format here if you
                   only have one custom post type. */
    
               <?php } ?>
        <?php } else { ?>
    
                  /* Format to display when the post_type parameter
                  is not set (i.e. default format) */
    <?php } ?>
    <?php endwhile; else: ?>
    
    /* What to display if there are no results. */
    
    <?php endif; ?>
    

    Naturally in all three places you'll need to replace "book" with your custom post type.

    Hope this helps someone!

  • A short code more actualized

     function template_chooser($template)   
    {    
      global $wp_query; 
      $post_type = $wp_query->query_vars["pagename"];   
      if( isset($_GET['s']) && $post_type == 'products' )   
      {
    
        return locate_template('archive-search.php');  //  redirect to archive-search.php
      }   
      return $template;   
    }
    add_filter('template_include', 'template_chooser'); 
    
  • I was looking to use two different forms for my normal searches and my searches on a custom post type.

    My custom post type uses a different header than normal pages, on my normal page, the call to my search form is:

    <?php get_search_form(true); ?>
    

    And the call to my search form in the custom post type header is:

    <?php get_template_part('search','library'); ?>
    

    Which has an additional field:

    <input type="hidden" name="post_type" value="library" /> //Where "library" is my custom post type.
    

    In the functions file I have the following code that you have provided.

    /** Custom Search for Library */
    function search_library($template)   
    {    
      global $wp_query;   
      $post_type = get_query_var('post_type');   
      if( $wp_query->is_search && $post_type == 'library' )   
      {
        return locate_template('search-library.php');  //  redirect to archive-search.php
      }   
      return $template;   
    }
    add_filter('template_include', 'search_library');
    

    Which detects if the search form is doing a search within custom fields, thus showing the search in a custom template, otherwise use the normal template.

    Edit: fixed the get_search_form() function call which would have returned true no matter what.

    Worth noting, but `get_search_form('true')` should be `get_search_form(true)`. `get_search_form` is looking for a boolean input, so either `true` or `false`. By wrapping it in quotes you are feeding it a string, not a boolean parameter. The way that function is set up, both `'true'` and `'false'` would return the same result, because they are both non-empty strings (which causes the function to return true in both cases).

  • To fix the empty input search issue you can substitute the function code with this:

    function template_chooser($template)   
    {    
     global $wp_query;   
     $post_type = get_query_var('post_type');   
     if( isset($_GET['s']) && $post_type == 'products' )   
     {
      return locate_template('archive-search.php');  //  redirect to archive-search.php
     }   
     return $template;   
    }
    add_filter('template_include', 'template_chooser');
    

    Would be great if you explain how your code works, an reveal your source of the code

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM