By default, when you search on a WordPress site, your search URL has an /?s=
parameter. Back in the old days of WordPress, we all had URLs like /?p=123
where 123 was the page ID. With the advent of Pretty Permalinks, we moved to pretty URLs like /2016/prettier-search-queries/
and everyone was happier.
What about search?
As it happens, the WP Rewrite API actually has a search base of … search. If you go to your Settings > Permalinks page, you won’t see it there, and yet on every site if you go to https://halfelf.org/search/apache
you’ll actually get that nice, pretty path.
Because of that, you could get away with adding this to your .htaccess
file in order to get those pretty URLs.
RewriteCond %{QUERY_STRING} s=(.*) RewriteRule ^$ /search/%1? [R,L]
You can also use a plugin like Mark Jaquith’s Nice Search.
Those methods work for nearly all sites.
But you know me. I’m not ‘all’ sites.
Extra Paramater Headache
I had a different problem. Because my site had specialized data, it had extra search parameters. I was intentionally limiting my search to specific post type. This meant my URLs looked like this: /?s=rookie+blue&post_type[]=post_type_shows
When I translated that to use the pretty search, well …/search/rookie+blue&post_type[]=post_type_shows
just didn’t work.
This is for a pretty obvious reason when you study the URLs. The first one has ?s=...
and then later an &
, while the second only has the &
in there. If I changed the URL to this, it worked: /search/rookie+blue/?post_type[]=post_type_shows
The reason for this was due to how parameters work in URLs. They have to start with ?
at the beginning. All additional parameters are added with ?param=value
after that.
Semi Pretty Search Permalinks
To me, the nicest URLs would be `/search/rookie+blue/section/shows/’. The reality is that people will search shows and characters and I wasn’t quite sure how I wanted to handle that. Did I want them to be sections separated by plus signs, or extra ‘folders’ or what? In the end, I decided that for now it was okay to just make these prettier.
Taking Mark’s code as my start point, I came up with this:
function pretty_permalink_search_redirect() { // grab rewrite globals (tag prefixes, etc) // https://codex.wordpress.org/Class_Reference/WP_Rewrite global $wp_rewrite; // if we can't get rewrites or permalinks, we're probably not using pretty permalinks if ( !isset( $wp_rewrite ) || !is_object( $wp_rewrite ) || !$wp_rewrite->using_permalinks() ) return; // Set Search Base - default is 'search' $search_base = $wp_rewrite->search_base; if ( is_search() && !is_admin() && strpos( $_SERVER['REQUEST_URI'], "/{$search_base}/" ) === false ) { // Get Post Types $query_post_types = get_query_var('post_type'); if ( is_null($query_post_types) || empty($query_post_types) || !array($query_post_types) ) { $query_post_types = array( 'post_type_characters', 'post_type_shows' ); } $query_post_type_url = '/?'; foreach ( $query_post_types as $value ) { $query_post_type_url .= '&post_type[]=' . $value ; } wp_redirect( home_url( "/{$search_base}/" . urlencode( get_query_var( 's' ) ) . urldecode( $query_post_type_url ) ) ); exit(); } } add_action( 'template_redirect', 'pretty_permalink_search_redirect' );
And that actually does work exactly as I want it to.