Crystal Ball Programming and Why Your Searchbox Failed
Your form fails because of this:
action="<?php bloginfo('template_url'); ?>/MilkNHny/search.php"
You should never directly call a template via URL.
Your template assume the WordPress environment has been loaded, which is a fair assumption. However, because you called it directly, it has not.
Search.php is the template WordPress looks for when it does a search. It doesnt do the actual search. If we apply some logic, browser goes to search.php, and immediatley tries to display the results without:
- bothering to actually perform the search
- loading plugins and themes
- checking rewrite rules
- sanitising data
Since PHP has no crystal ball functionality, things error out. Sorry if it seems brutal, but the point needed demonstrating effectively.
Remember, a computer does as it’s told, not as it’s expected. If you can’t answer the question “Why would it do that?” or “how does it know?” then there’s a very, very good chance that it doesn’t know, and it doesn’t do that, and things are going to blow up spectacularly.
How a Search Request Works
When you go to a URL, WordPress looks up a big list of regular expressions and sees which is the first one that matches. These ‘regexes’ tell WordPress how to map /category/example-category/hello-world
into something it can pass into WP_Query, e.g. name=hello-world
. The parameters are identical to those used in WP_Query, which is where the post loop comes from.
One of these parameters is s
. The search form passes in the search query via the URL e.g.:
example.com/?s=helloworld
WordPress then passes this s
parameter into its main loop query, and makes a mental note:
“hey the
s
thing is there, this must be a search query! Does the theme have a search.php? LOAD THE SEARCH.PHP TEMPLATE!!!!!! ( ps: load index.php if we don’t )
So now WordPress goes off and somewhere there’s a WP_Query( array ( 's' => 'helloworld' ) )
, and it’s all wrapped up so you can then print it out using have_posts etc
So The Basic Search Form is?
So now that we know how a search query works, lets see the basic markup:
<form method="GET" action="<?php echo home_url(); ?>">
<input type="text" name="s">
</form>
- method=”GET” because GET variables are passed in the URL, POST variables are passed in headers we don’t see in the address bar
home_url()
because that’s the main index of the site. We could search within a category of a date archive by putting ?s= on the end of other pages, but lets assume we want to search the entire sitename="s"
because this is the query var WordPress uses to specify a search string
We can expand this further using other functions such as get_search_query()
etc, but those aren’t necessary.
A Bonus
You don’t need to submit a search string from the frontend either. Say you wanted to add a box that listed posts containing the word “Moomins” ( because everyone loves moomins ).
I could do this by doing a post query with the s
parameter, e.g.:
$q = new WP_Query( 's=Moomins' );
$while ( $q->have_posts() ) {
$q->the_post();
the_title();
}
wp_reset_postdata(); // clean up after ourselves
And hey presto, a list of titles of posts from a search for “Moomins”