Pretty permalinks for search results with extra query var

The question:

I’d like to know how I can rewrite a search URL that also contains an extra query var into a pretty permalink using wp_redirect and the template_redirect hook.

I have taken the code from the Nice Search plugin which works fine to change http://example.com?s=africa into http://example.com/search/africa:

add_action( 'template_redirect', 'my_rewrite' ) );

function my_rewrite() {

        if ( is_search() and false === strpos( $_SERVER['REQUEST_URI'], '/search/' ) ) {
            wp_redirect( get_bloginfo( 'home' ) . '/search/' . str_replace( ' ', '+', str_replace( '%20', '+', get_query_var( 's' ) ) ) );
            exit();
        }

    }

But I am using a select dropdown in combination with the Relevanssi plugin to allow visitors to narrow down the search to a particular post type. This adds a post_type query var, e.g. http://example.com?s=africa&post_type=features. I would like this to have a URL something like http://example.com/search/africa/section/features.

The Nice Search code causes the post_type query var to be lost. So I tried the following code:

function my_rewrite() {

    if ( is_search() and false === strpos( $_SERVER['REQUEST_URI'], '/search/' ) ) {
        if ( isset( $_GET['post_type'] ) and '' !== $_GET['post_type'] ) {
            wp_redirect( get_bloginfo( 'home' ) . '/search/' . str_replace( ' ', '+', str_replace( '%20', '+', get_query_var( 's' ) ) ) . '/section/' . str_replace( ' ', '+', str_replace( '%20', '+', get_query_var( 'post_type' ) ) ) );
        } else {
            wp_redirect( get_bloginfo( 'home' ) . '/search/' . str_replace( ' ', '+', str_replace( '%20', '+', get_query_var( 's' ) ) ) );
        }
        exit();
    }

}

but WordPress now thinks the search term is africa/section/features.

Is there a way I can keep the search term and the query var all in a nice permalink?

Thanks
Simon

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

To modify the search rewrite rules you can hook into the search_rewrite_rules filter. You can either add the extra rewrite rules that match post types yourself, or you can change the default “search rewrite structure” to also include the post type and then re-generate the rules (there are four rules: one standard, one with paging and two for feeds). Because WP_Rewrite::generate_rewrite_rules() generates rules at every “directory level”, you will get rules for /search/[keyword]/section/[post_type]/, /search/[keyword]/section/ and /search/[keyword]/. You don’t need the middle rule, but it won’t hurt to keep it in.

add_filter( 'search_rewrite_rules', 'wpse15418_search_rewrite_rules' );
function wpse15418_search_rewrite_rules( $search_rewrite_rules )
{
    global $wp_rewrite;
    $wp_rewrite->add_rewrite_tag( '%post_type%', '([^/]+)', 'post_type=' );
    $search_structure = $wp_rewrite->get_search_permastruct();
    return $wp_rewrite->generate_rewrite_rules( $search_structure . '/section/%post_type%', EP_SEARCH );
}

To check the rules, use my Rewrite analyzer plugin.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment