Custom post type permalink endpoint

I have a custom post type called “destinations” and I have set the EP mask for the post type to default EP_PERMALINK. I have added a couple of endpoints as follows :

add_filter( 'query_vars', 'add_query_vars');

function add_query_vars($vars){
    $vars[] = "tours";
    $vars[] = "activities";
    return $vars;
}

add_action('init', 'add_endpoints');

function add_endpoints(){
    global $wp_rewrite; 

    add_rewrite_endpoint('tours', EP_PERMALINK);
    add_rewrite_endpoint('activities', EP_PERMALINK);

    $wp_rewrite->flush_rules();
}

Now if I test this on a normal post it redirects to the template that I need it to (I have a template redirect for the single template hook)

ie. somesite.com/test-category/test/activities/

But for the post type (which is hierarchical) it just removes the endpoint from the url and stays on the single-destination.php template

ie. somesite.com/destination/south-africa/kruger-national-park/activities/

becomes

somesite.com/destination/south-africa/kruger-national-park/

Any help or guidance will be greatly appreciated. I have been struggling with this for hours and no results 🙁

Thanks

1
1

A couple things. First, your function names need to be prefixed with something unique. WordPress is a big ecosystem, and someone else has probably used all the generic function names you can think of.

Second, add_rewrite_endpoint takes care of adding query variables for you. So you don’t need this:

add_filter( 'query_vars', 'add_query_vars');
function add_query_vars($vars){
    $vars[] = "tours";
    $vars[] = "activities";
    return $vars;
}

Flushing rewrite rules on every load is not a good idea. This only needs to be done once after your rules have been added. Like on plugin activation. So you add_endpoints function could be shorted to this (with a better function name per point one above).

<?php
add_action('init', 'wpse42279_add_endpoints');
function wpse42279_add_endpoints()
{
    add_rewrite_endpoint('tours', EP_PERMALINK);
    add_rewrite_endpoint('activities', EP_PERMALINK);
}

Which works fine for posts. If you want it to work on pages or any other hierarchical post type, you’ll have to use the EP_PAGES endpoint mask.

<?php
add_action('init', 'wpse42279_add_endpoints');
function wpse42279_add_endpoints()
{
    add_rewrite_endpoint('tours', EP_PAGES);
    add_rewrite_endpoint('activities', EP_PAGES);
}

But that’s still not going to work as expected for you. Endpoints set their query variable equal to whatever comes after it. So if your URL is…

yoursite.com/some-country/some-city/activities/asdf

the query variable activities will be asdf. If nothing follows activities, your query var will be empty (but set), so it will always evaluate as false when you try to catch it…

<?php
add_action( 'template_redirect', 'wpse42279_catch_vars' );
function wpse42279_catch_vars()
{
    if( get_query_var( 'tours' ) )
    {
        // do stuff!
        exit();
    }
}

You can get around this by filtering request and changing the value of your tours and activities variables to true if they are set.

<?php
add_filter( 'request', 'wpse42279_filter_request' );
function wpse42279_filter_request( $vars )
{
    if( isset( $vars['tours'] ) ) $vars['tours'] = true;
    if( isset( $vars['activities'] ) ) $vars['activities'] = true;
    return $vars;
}

You should have a look at this guide to the Rewrite API I wrote. The relevant parts for your question are summed up above, however.

Leave a Comment