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:

Read More

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.

Related posts

2 comments

  1. 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) != "/") $myurl .= "/";
                $myurl .= "state/";
                $myurl .= trim( sanitize_title_for_query( $_REQUEST['state'] ) ) . "/";
                exit( wp_redirect( $myurl ) ) ;
            }
        }
    }
    add_action( 'template_redirect', 'my_template_redirect' );
    

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

  2. Maybe this is not the best solution, nor the solution you are looking for, but this comes in my mind now, someone can maybe give you another.

    I think in the page form you have something like this:

    <select name="state">
       <option value="austria">Austria</option>
       ...
    </select>
    

    Using javascript it’s easy send user to the pretty url.

    (I put javascript here, you ensure put it in a separate js file and enqueue it with wp_enqueue_script)

    Untested:

    jQuery().ready(function($) {
      $('select[name="state"]').change(function(e){
        e.preventDefault();
        var state = $(this).children('option:selected').val();
        window.location.href = window.location.href + '/' + state;
      });
    });
    

Comments are closed.