How To Add Search To A WordPress Theme

How To Add Search To A WordPress Theme

Let’s now tackle the task of adding a search box to our custom WordPress Theme. The built-in WordPress search function which is a part of the WordPress core is actually quite capable as compared to what it was when WordPress was just a new CMS. In this tutorial, we will learn how to add a search field somewhere in the upper right-hand area of the site. In addition to this, we will learn how to format the relevant search results that WordPress provides back to us when making a search query.


Adding Search Box To Header.php

We mentioned that we would like to add that search field in the upper right area of the site, so what theme file do you think we might target to make modifications? That’s right, we’ll need to open up the header.php file and figure out a way to add some search functionality. We can do this with the built-in get_search_form() function, and also adding just a bit of CSS styling rules to our style.css file. Here are our updated header.php and a relevant snippet from the style.css file.

header.php

<!DOCTYPE html>
<html <?php language_attributes(); ?>>

<head>
    <meta charset="<?php bloginfo( 'charset' ); ?>">
    <title><?php bloginfo( 'name' ); ?></title>
	<?php wp_head() ?>
</head>

<body <?php body_class(); ?>>
<div class="container">
    <header class="site-header">
        <div class="header-search">
			<?php get_search_form(); ?>
        </div>
        <h1><a href="<?php echo home_url(); ?>"><?php bloginfo( 'name' ); ?></a></h1>
        <h4><?php bloginfo( 'description' ); ?></h4>
        <nav class="navigation-menu">
			<?php $args = [ 'theme_location' => 'primary' ]; ?>
			<?php wp_nav_menu( $args ) ?>
        </nav>
    </header>
	<?php if ( is_page( 'about-us' ) ) : ?>
    <h3>Thanks for visiting our page!</h3>
<?php endif ?>

style.css

.header-search {
    float: right;
}

Here is our resulting form so far.
get_search_form function output

We got it working! Well, we at least have a search box displaying on the page now. So notice how we did this. We set up a wrapping div element that has a class of ‘header-search’, that way we could target that element for CSS styling. Then, in our style.css file, we added that rule of floating the search box to the right. As we can see in the screenshot, it looks like we now have a decent-looking search box in the upper right-hand area of our theme.


How To Customize The WordPress Search Form

What if you would rather have more control over the HTML that gets output from the get_search_form() function? Well first off, let’s have a look at the HTML that gets output to the screen when we simply call that function as we did above.

Default Output of get_search_form() function

<form role="search" method="get" id="searchform" class="searchform" action="http://wordpresstutorial.dev/">
  <div>
    <label class="screen-reader-text" for="s">Search for:</label>
    <input value="" name="s" id="s" type="text">
    <input id="searchsubmit" value="Search" type="submit">
  </div>
</form>

We can see that the get_search_form() function automatically creates an opening and closing form tag. The from has a role of ‘search’, its method is set to ‘get’, it has an ‘id’ of ‘searchform’, a class of ‘searchform’, and an action of ‘http://wordpresstutorial.dev/’. These all seem like sensible defaults. Within the form tag, a wrapping div tag is set up which contains two input tags and a label tag. The label tag has a class of ‘screen-reader-text’, and it’s for attribute set to ‘s’. This means that this label is targeting the element with an id of ‘s’. This makes sense as the input tag with a type of ‘text’ has an id and name of ‘s’. Finally, a search button is set up automatically for us with the input tag which has an id of ‘searchsubmit’ a value of ‘Search’, and a type of ‘submit’. So you can see, the get_search_form() function actually does quite a lot for us.


Replacing The Default HTML output of the get_search_form() function with searchform.php

Go ahead and create a new theme file in your custom theme folder and name it searchform.php. If you go back and reload your WordPress set, you will now notice that your search form is gone from the page! What happened? This is because, if there is a file of searchform.php in your theme, WordPress will use the contents of that file to handle the output of the get_search_form() function instead of using the default output.

Let’s add some code to our searchform.php file now. We’ll actually make use of the same code WordPress uses by default, but we will also need to make use of a special function named home_url().
searchform.php

<form role="search" method="get" id="searchform" class="searchform" action="<?php echo home_url( '/' ); ?>">
    <div>
        <label class="screen-reader-text" for="s">Search for:</label>
        <input value="" name="s" id="s" type="text">
        <input id="searchsubmit" value="Search" type="submit">
    </div>
</form>

Let’s also make the button look a little better with some custom css. Here is the css rules we can apply to style.css to make our search form and button look just little less bland.

#searchsubmit {
    background-color: #00a0d2;
    color: white;
    padding: 5px 8px;
    font-size: 15px;
    line-height: 1.3;
    border-radius: 6px;
    cursor: pointer;
}

#s {
    height: 18px;
    padding: 5px 8px;
    font-size: 15px;
    line-height: 1.1;
    border-radius: 6px;
}

Looks pretty good now!
custom styled wordpress search box


How Does WordPress Handle Search Results?

Now that we have our search box looking pretty good on our site, let’s talk a little bit about how WordPress actually handles the search query and results. Up above, we noticed that the ‘action’ attribute of the form tag for our search form had its value set to the home url of our site. In our case, that is http://wordpresstutorial.dev/. You can output your home url with the function home_url() as we also learned. Now, what does that action attribute actually mean? Well, when a user submits a search query, this is where the search gets sent to. Specifically, in WordPress, a ‘get’ request is made of the home url. Now go ahead and do a search, we will search for ‘JavaScript blog’ in our example.
example wordpress search result page

We get a reasonable result. What we want to focus on however is the mechanics of how this worked. Let’s inspect the URL you see in the browser window after we completed the search.

Action:
search using get request action

Name:
search query in url

Search Text:
url encoded search request

You can easily see which parts of the code contained in searchform.php correspond to how the URL gets populated during a WordPress search query that uses a GET request. Now that we see how the WordPress search url is constructed, what about how the results actually get displayed on the page. Well, as it stands now in our custom theme, we do not have a special file that handles outputting the search results of a WordPress query. Do you want to take a guess at which file handles those search results then? Yep, that’s right! It is our workhorse index.php file which takes care of displaying results in this case. Of course, like everything else in WordPress, we can create our own file to handle this as well if we like. We can do this by creating a file named search.php in our theme folder. A common approach to use is to copy the contents of what you currently have in your index.php file into the search.php file, and then customize that search.php file to make the search results look exactly how you want them to.


Display The Search Term The User Entered

A really neat thing to add to your search results page is some heading type text that tells the user what they searched for. So for our last query, it might be nice for the string of something like Search results for query: “JavaScript blog” to be displayed to the user. We can do just that with the function provided by WordPress named the_search_query(). I think we will also use PHP to populate the search form itself with the query we type in. We will need to customize search.php to display the search string we want, and searchform.php to populate the text area with the query. Here are those snippets highlighted.

search.php

<?php

get_header();

if ( have_posts() ) :
	?>
    <h2>Search results for query: "<?php the_search_query(); ?>"</h2>
	<?php
	while ( have_posts() ) : the_post(); ?>

        <article class="post">
			<?php if ( has_post_thumbnail() ) { ?>
                <div class="small-thumbnail">
                    <a href="<?php the_permalink() ?>"><?php the_post_thumbnail( 'small-thumbnail' ); ?></a>
                </div>
			<?php } ?>
            <h2><a href="<?php the_permalink() ?>"><?php the_title() ?></a></h2>
            <p class="post-meta"><?php the_time( 'F jS, Y' ); ?> | <a
                        href="<?php echo get_author_posts_url( get_the_author_meta( 'ID' ), get_the_author_meta( 'user_nicename' ) ); ?>"><?php the_author(); ?></a>
                | <?php
				$categories = get_the_category();
				$comma      = ', ';
				$output     = '';
				
				if ( $categories ) {
					foreach ( $categories as $category ) {
						$output .= '<a href="' . get_category_link( $category->term_id ) . '">' . $category->cat_name . '</a>' . $comma;
					}
					echo trim( $output, $comma );
				} ?>
            </p>
            <p>
				<?php echo get_the_excerpt() ?>
                <a href="<?php the_permalink() ?>">Read more &raquo</a>
            </p>
        </article>
	
	<?php endwhile;

else :
	echo '<p>No search results found!</p>';

endif;

get_footer();

?>

searchform.php

<form role="search" method="get" id="searchform" class="searchform" action="<?php echo home_url( '/' ); ?>">
    <div>
        <label class="screen-reader-text" for="s">Search for:</label>
        <input value="" name="s" id="s" type="text" placeholder="<?php the_search_query(); ?>">
        <input id="searchsubmit" value="Search" type="submit">
    </div>
</form>

Let’s go ahead and try that same query and see if we are getting the results we are aiming for. It looks like things are working perfectly. The user types in the query text and clicks submit, the get request is properly formatted in the url, and we get the results we want with some nice output to the screen as well letting us know what we searched for.
wordpress search cycle of events

Don’t Repeat Yourself (DRY) with get_template_part()
This is a good time to introduce the get_template_part() function which helps developers to reduce code duplication in their themes. You might have noticed that the code we have in search.php, index.php, single.php, and archive.php all have almost identical code in the loop. In other words, the part of our markup that begins and ends with the <article> tag is repeated in all of these files. Is there a better way? Yes there is. Go ahead and create a new file called ‘theposts.php’. We can add the following code to it:

theposts.php

<article class="post">
	<?php if ( has_post_thumbnail() ) { ?>
        <div class="small-thumbnail">
            <a href="<?php the_permalink() ?>"><?php the_post_thumbnail( 'small-thumbnail' ); ?></a>
        </div>
	<?php } ?>
    <h2><a href="<?php the_permalink() ?>"><?php the_title() ?></a></h2>
    <p class="post-meta"><?php the_time( 'F jS, Y' ); ?> | <a
                href="<?php echo get_author_posts_url( get_the_author_meta( 'ID' ), get_the_author_meta( 'user_nicename' ) ); ?>"><?php the_author(); ?></a>
        | <?php
		$categories = get_the_category();
		$comma      = ', ';
		$output     = '';
		
		if ( $categories ) {
			foreach ( $categories as $category ) {
				$output .= '<a href="' . get_category_link( $category->term_id ) . '">' . $category->cat_name . '</a>' . $comma;
			}
			echo trim( $output, $comma );
		} ?>
    </p>
    <p>
		<?php echo get_the_excerpt() ?>
        <a href="<?php the_permalink() ?>">Read more &raquo</a>
    </p>
</article>

With that file in place, we can now make use of get_template_part() in our search.php file. Let’s see how!
search.php

<?php

get_header();

if ( have_posts() ) {
	?>
    <h2>Search results for query: "<?php the_search_query(); ?>"</h2>
	<?php
	while ( have_posts() ) {
		the_post();
		get_template_part( 'theposts' );
	}
} else {
	echo '<p>No search results found!</p>';
}

get_footer();

?>

You test out the search function again and you will find that everything still works great. Now, we can also simplify both the index.php file and the archive.php file since they both use that same repetitive code. Let’s see those updated files now.

index.php

<?php

get_header();

if ( have_posts() ) {
	while ( have_posts() ) {
		the_post();
		get_template_part( 'theposts' );
	}
} else {
	echo '<p>There are no posts!</p>';
}

get_footer();

?>

archive.php

<?php

get_header();

if ( have_posts() ) {
	?>
    <h2><?php
		if ( is_category() ) {
			single_cat_title( 'Category Archive: ' );
		} elseif ( is_tag() ) {
			single_tag_title( 'Tag Archive: ' );
		} elseif ( is_author() ) {
			the_post();
			echo 'Author Archives: ' . get_the_author();
			rewind_posts();
		} elseif ( is_day() ) {
			echo 'Daily Archives: ' . get_the_date();
		} elseif ( is_month() ) {
			echo 'Monthly Archives: ' . get_the_date( 'F Y' );
		} elseif ( is_year() ) {
			echo 'Yearly Archives: ' . get_the_date( 'Y' );
		} else {
			echo 'Archives: ';
		}
		?></h2>
	<?php
	while ( have_posts() ) {
		the_post();
		get_template_part( 'theposts' );
	}
} else {
	echo '<p>There are no posts!</p>';
}

get_footer();

?>

I think you would agree that these files are now more streamlined and simplified. Any time we need to output the posts within the WordPress loop now, we can simply reference that get_template_part() function to pull in the needed code for us. Notice that the string you pass in as an argument to get_template_part() is the actual name of the file for which you want to include. You can make as much or as little use of this function as you like. Some people prefer to keep it DRY, while others like to just have a dedicated file for which they know to reach for if they need to make a change in their theme.


How To Add Search To A WordPress Theme Summary

In this tutorial, we had a good look at how to add a simple search box to our WordPress theme. We placed our search form in the header.php file with the help of the get_search_form() function and some custom CSS styles. We saw that you can customize the search form HTML output if you like by creating a searchform.php file in your theme. Your search results are displayed via the index.php file unless you decide to add a search.php file to your theme to handle the search query results for you. Lastly, we took some time to dry up our code by making use of the get_template_part() function.