Pretty permalinks for search results with extra query var

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

1
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//section/[post_type]/, /search//section/ and /search//. 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.

Leave a Comment