1

I've been reading around a lot on here and Google to do with custom rewrite rules in WordPress and add_rewrite_rule. I found Jan Fabry's answer particularly helpful, but I'm now a bit stuck.

I am using the following code to enable 3 matches in a URL,

add_action( 'init', 'wpa5413_init' );
function wpa5413_init()
{

    // Remember to flush the rules once manually after you added this code!
    add_rewrite_rule(
        // The regex to match the incoming URL
        'our-work/our-year/([^/]*)/([^/]*)/([^/]*)/?',
        // The resulting internal URL: `index.php` because we still use WordPress
        // `pagename` because we use this WordPress page
        // `designer_slug` because we assign the first captured regex part to this variable
        'index.php?pagename=our-work/our-year&our_year_tax_slug=$matches[1]&our_quarter_tax_slug=$matches[2]&our_work_post_slug=$matches[3]',
        // This is a rather specific URL, so we add it to the top of the list
        // Otherwise, the "catch-all" rules at the bottom (for pages and attachments) will "win"
        'top' );
}

add_filter( 'query_vars', 'wpa5413_query_vars' );
function wpa5413_query_vars( $query_vars )
{
    $query_vars[] = 'our_year_tax_slug';
    $query_vars[] = 'our_quarter_tax_slug';
    $query_vars[] = 'our_work_post_slug';
    return $query_vars;
}

It is slightly modified from Jan Fabry's answer. I am using ([^/]*) instead of ([^/]+) although I have found that using either makes no difference to the result for me. I am also using it on a child page, so I've included the parent page in the initial regex match and the pagename= value.

It works perfectly well with all 3 values specified. When I use the following code in a template:

<?php 

    echo get_query_var( 'our_year_tax_slug' );
    echo "<br>";
    echo get_query_var( 'our_quarter_tax_slug' );
    echo "<br>";
    echo get_query_var( 'our_work_post_slug' );

?>

and access the URL like test.dev/our-work/our-year/one/two/three/ I get one two three printed on the page. The problem is, I also want test.dev/our-work/our-year/one/two/ and test.dev/our-work/our-year/one/ to work. However if I try and access these URLs I get a 404.

I tried adding two more sets of add_rewrite_rules, like so:

add_action( 'init', 'wpa5413_init' ); function wpa5413_init() { // Remember to flush the rules once manually after you added this code! add_rewrite_rule( // The regex to match the incoming URL 'our-work/our-year/([^/]*)/?', // The resulting internal URL: index.php because we still use WordPress // pagename because we use this WordPress page // designer_slug because we assign the first captured regex part to this variable 'index.php?pagename=our-work/our-year&our_year_tax_slug=$matches1', // This is a rather specific URL, so we add it to the top of the list // Otherwise, the "catch-all" rules at the bottom (for pages and attachments) will "win" 'top' );

    // Remember to flush the rules once manually after you added this code!
    add_rewrite_rule(
        // The regex to match the incoming URL
        'our-work/our-year/([^/]*)/([^/]*)/?',
        // The resulting internal URL: `index.php` because we still use WordPress
        // `pagename` because we use this WordPress page
        // `designer_slug` because we assign the first captured regex part to this variable
        'index.php?pagename=our-work/our-year&our_year_tax_slug=$matches[1]&our_quarter_tax_slug=$matches[2]',
        // This is a rather specific URL, so we add it to the top of the list
        // Otherwise, the "catch-all" rules at the bottom (for pages and attachments) will "win"
        'top' );

    // Remember to flush the rules once manually after you added this code!
    add_rewrite_rule(
        // The regex to match the incoming URL
        'our-work/our-year/([^/]*)/([^/]*)/([^/]*)/?',
        // The resulting internal URL: `index.php` because we still use WordPress
        // `pagename` because we use this WordPress page
        // `designer_slug` because we assign the first captured regex part to this variable
        'index.php?pagename=our-work/our-year&our_year_tax_slug=$matches[1]&our_quarter_tax_slug=$matches[2]&our_work_post_slug=$matches[3]',
        // This is a rather specific URL, so we add it to the top of the list
        // Otherwise, the "catch-all" rules at the bottom (for pages and attachments) will "win"
        'top' );
}

But this did not work. I now only am able to access the first query var (our_year_tax_slug) even though test.dev/our-work/our-year/one/two/three, test.dev/our-work/our-year/one/two/ and test.dev/our-work/our-year/one/ all work without a 404 error, the template code only prints out the first value - one, no matter which URL is accessed.

I'm sure someone must have come across this problem before, any help would be greatly appreciated. I am clicking saving permalinks every time I update the functions.php file. Thanks

1

Well, apparently lots of trial and error pays off!

I used this code instead, where I reversed my add_rewrite_rules and now it works perfectly.

// Remember to flush the rules once manually after you added this code!
add_rewrite_rule(
    // The regex to match the incoming URL
    'our-work/our-year/([^/]*)/([^/]*)/([^/]*)/?',
    // The resulting internal URL: `index.php` because we still use WordPress
    // `pagename` because we use this WordPress page
    // `designer_slug` because we assign the first captured regex part to this variable
    'index.php?pagename=our-work/our-year&our_year_tax_slug=$matches[1]&our_quarter_tax_slug=$matches[2]&our_work_post_slug=$matches[3]',
    // This is a rather specific URL, so we add it to the top of the list
    // Otherwise, the "catch-all" rules at the bottom (for pages and attachments) will "win"
    'top' );

// Remember to flush the rules once manually after you added this code!
add_rewrite_rule(
    // The regex to match the incoming URL
    'our-work/our-year/([^/]*)/([^/]*)/?',
    // The resulting internal URL: `index.php` because we still use WordPress
    // `pagename` because we use this WordPress page
    // `designer_slug` because we assign the first captured regex part to this variable
    'index.php?pagename=our-work/our-year&our_year_tax_slug=$matches[1]&our_quarter_tax_slug=$matches[2]',
    // This is a rather specific URL, so we add it to the top of the list
    // Otherwise, the "catch-all" rules at the bottom (for pages and attachments) will "win"
    'top' );

 // Remember to flush the rules once manually after you added this code!
add_rewrite_rule(
    // The regex to match the incoming URL
    'our-work/our-year/([^/]*)/?',
    // The resulting internal URL: `index.php` because we still use WordPress
    // `pagename` because we use this WordPress page
    // `designer_slug` because we assign the first captured regex part to this variable
    'index.php?pagename=our-work/our-year&our_year_tax_slug=$matches[1]',
    // This is a rather specific URL, so we add it to the top of the list
    // Otherwise, the "catch-all" rules at the bottom (for pages and attachments) will "win"
    'top' );

I would guess this has something to do with the 'top' parameter on the add_rewrite_rule. Most likely its some kind of other mystical magic I have no idea about. I'd be interested to find out exactly what is going on here though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.