WordPress URL Routing, Multiple permalinks with different templates

This question is based on an unanswered question in WordPress Development which has not gotten a solid answer.

I have a wordpress website which lists hotels. the url for a single hotel looks like:

Read More

/hotels/the-marriot-hotel

I also have a custom taxonomy for Locations, which allows me to browse the hotels in various locations, which works fine, the urls are like:

/Locations/Liverpool

For URL’s like /hotels/* I would like to use a custom template, which I have done already and works fine.

The Problem

I also want to be able to drilldown the Locations taxonomy creating a breadcrumb type URL and also use a different template for the hotel page.

For Example, if a user is browsing /Locations/Liverpool and clicks the Marriot Hotel I would like it to click through to /Locations/Liverpool/the-marriot-hotel instead of /hotels/the-marriot-hotel and also use a slightly different template, which can also load a different sidebar and recommend other hotels in the area specific to the location slug in the URL

So basically I want two routes to a single post and a different template used based on the route used.

How would I go about implementing this?

What have I tried?

I’ve tried adding a new page and using a rewrite rule to point to it to be the locations hotel page.

I’ve tried adding a slug on the end of the /Locations/{location-slug} url and reading this in the page template and loading the hotel post instead of the list it doesn’t seem to be working but also feels like a terrible hack anyway

An idea that I’ve had is to add a rewrite to the hotels/{slug} page and using code to detect the URL used and switch templates dynamically but I’m not sure this is the best approach

Related posts

Leave a Reply

1 comment

  1. I have managed to get this working using the second method mentioned above (adding a rewrite to the locations landing page and checking for a query_var).

    I will post the code below that I used but although this works and seems to be working very well, It does not feel like the best way of doing it. If someone know of a better way of doing this please post the answer.

    I used this online post for reference.

    Note: The listing page shows the list of hotels in the taxonomy in a side column down the side and shows the currently selected or a random one in the main content area. Which will explain how I am using the loop below.

    function prefix_locations_rewrite_rule() {
        add_rewrite_rule( 'Locations/([^/]+)/([^/]+)', 'index.php?locations=$matches[1]&hotel=$matches[2]', 'top' );
    }
    
    function prefix_register_query_var( $vars ) {
        $vars[] = 'hotel';
    
        return $vars;
    }
    
    function prefix_url_rewrite_templates() {
    
        if ( get_query_var( 'hotel' ) && is_singular( 'hotel' ) ) {
            add_filter( 'template_include', function() {
                return get_template_directory() . '/taxonomy-locations.php';
            });
        }
    }
    
    add_action( 'template_redirect', 'prefix_url_rewrite_templates' );
    add_filter( 'query_vars', 'prefix_register_query_var' );
    add_action( 'init', 'prefix_locations_rewrite_rule' );
    

    In my template file for the hotels landing page:

    $hotelSlug = get_query_var( 'hotel', false);
    
    if ( have_posts() ) {
        while (have_posts()) : the_post();
    
            if ($post->post_name == $hotelSlug) {
                break;
            }
    
        endwhile;
    }
    

    This bit of code will iterate over the posts and if the hotel slug matches the query var it will break there so that the current post is the one we wanted.

    We could just use a query here but as I already have a list of posts within the taxonomy I thought I’d just iterate over it. Below this I check to see if a specific hotel has been selected otherwise I show a random one from the list.

    I am still to add additional logic and error handling to this code, I hope it helps someone with a similar issue