Custom query variable – get wordpress to redirect to nice permalink url

I have been looking for an answer for the last couple of hours but could not find anything pointing me in the right direction. Some advice would be very much appreciated!

  • What I already have:
    • A custom post type 'stores'
    • A public query var using the 'query_vars' filter hook: 'state'.
    • Added the according rewrite rule:
      • Pattern: stores/state/([^/]+)/?$
      • Match: index.php?post_type=stores&state=$matches[1]
    • As 'state' is a custom meta field, I added a function hooking into pre_get_posts action hook doing all the query magic (creating meta_query etc) to display only the matching stores in the archive page.

That’s all working quite well:

So if I enter www.myurl.com/stores/state/austria my archive page is only showing Austrian stores.

To filter the stores not only by url, the archive page includes a form to filter them. This is where I run into my problem: the form obviously only passes POST or GET data, e.g. like the following:

www.myurl.com/stores/?state=austria

I can deal with this by adding a check in my pre_get_posts filter function:

if( isset( $_REQUEST['state'] ) || $query->get('state') != "" ) {

However, this is a little dirty as I would like wordpress to automatically redirect to the rewritten URL:

www.myurl.com/stores/?state=austria

should be redirected to

www.myurl.com/stores/state/austria

the same way it is done if I enter a page or post ID and it redirects to the permalink.

Is there another action hook I have not discovered yet? How would I get wordpress to automatically redirect to the pretty permalink?

Thank you for every hint.

2 Answers
2

I figured out a solution myself. No javascript required, only another template function. URL building done manually.

The idea is to use the hook ‘template_redirect’, check if the requested page is the corresponding store archive page, then check for $_REQUEST vars there and build a new URL. Finally redirect to this URL.

function my_template_redirect() {
    if ( is_post_type_archive( 'stores' ) ) {
        if ( isset( $_REQUEST['state'] )  ) {
            $myurl = get_post_type_archive_link( 'stores' );
            if (substr($myurl, -1) != "https://wordpress.stackexchange.com/") $myurl .= "https://wordpress.stackexchange.com/";
            $myurl .= "state/";
            $myurl .= trim( sanitize_title_for_query( $_REQUEST['state'] ) ) . "https://wordpress.stackexchange.com/";
            exit( wp_redirect( $myurl ) ) ;
        }
    }
}
add_action( 'template_redirect', 'my_template_redirect' );

Works pretty well. Any corrections/better ideas are welcome of course.

Leave a Comment