add_rewrite_rule() vs $wp_rewrite->rules vs ‘rewrite_rules_array’?

The question:

I’ve written Rewrite rules for my custom post types. they work well except that WP doesn’t update the url in the User Agent when the redirect_url doesn’t match the requested_url.

everything else works great though including my custom permastructs (‘post_type_link’) and custom template options (‘single-template’).

my rules:

// custom URL rewrite for Album posts
add_action( 'init', 'gregory_rewrite_album_link' );
function gregory_rewrite_album_link()
{
    // album--%album_slug%/ OR album/%album_slug%/
    // preferred permastruct: album--%album_slug%/
    add_rewrite_rule(
        '^album(/|--)([^/]+)/?$',
        'index.php?post_type=gregory-cpt-album&name=$matches[2]',
        'top' );
}

// custom URL rewrite for Track posts
add_action( 'init', 'gregory_rewrite_track_link' );
function gregory_rewrite_track_link()
{
    // accepts and rewrites the following permutations:
    // where album would be: album--%album_slug% OR album/%album_slug%
    // where track would be: track--%track_slug% OR track/%track_slug%
    // preferred permastruct: album--%album_slug%/track--%track_slug%/
    add_rewrite_rule(
        '^(album(/|--)[^/]+/)?track(/|--)([^/]+)/?$',
        'index.php?post_type=gregory-cpt-track&name=$matches[4]',
        'top' );
}

I was wondering what the differences were between using add_rewrite_rule(), appending rules directly to $wp_rewrite->rules, and hooking into rewrite_rules_array? are there any differences? would one of the alternatives force WP to update the url in the User Agent when the targeted post’s permalink differed to the requested url?

one example of the url not updating… the album and track posts are linked by a mutual taxonomy term. the hook into ‘post_type_link’ for tracks finds the linked album and inserts its slug into the permalink. the Rewrite rules above make sure that both new and traditional permastructs work, but requesting this url /album/serenity/track--beetle-attack/ will find the post but not update the url to /album--serenity/track--beetle-attack/.

it’s unlikely that anyone will use the traditional permastructs because I won’t advertise them or use them in my site, but it’d be a nice extra to see the url’s get updated in the User Agent anyway, if possible.

cheers,
Gregory

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

First of all use add_rewrite_rule() over messing directly with $wp_rewrite->rules if possible. The latter is a bit low-level.

Regarding the ‘url not updating’ – this isn’t the job of the rewrite rules. These simply point urls to their content, but they don’t update the user’s address bar.

The file that is responsible for this is /wp-includes/canonical.php. In particular the function redirect_canonical() hooked onto template_redirect.

This redirect_canonical() has its own filter:

add_filter('redirect_canonical', 'wpse50912_redirect_canonical',10,2)
function wpse50912_redirect_canonical($redirect_url, $requested_url){

     //Do stuff - determine if url is requesting album/track and check
     //If it is, check it is using the new structure. 
     //Return the url you want in the address bar.

     return $redirect_url;
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment