add_rewrite_rule not loading correct page nor getting variables

All we need is an easy explanation of the problem, so here it is.

I’ve trying to get a showreel title and video id into an URL that can then be accessed by the page.

i have the two in the same URL and it either doesn’t work or only one comes in. Currently the page isn’t being found ? (i am constantly flushing the permalinks)

Url i want to get variables from will look like
directors/test-director/showreel/showreel-name/video/111/

The site currently sits in a testing folder called independent_02 but not sure if that affects anything?

here’s the code;

function wpse13483_init() {

    add_rewrite_rule( 'directors/(.+?)/showreels/([^/]+)?/?$', 'index.php?category_name=$matches[1]&showreel=a', 'top' );
    add_rewrite_rule( 'directors/(.+?)/showreels/([^/]+)/video/([^/]+)?/?$', 'index.php?category_name=$matches[1]&showreel=c1&video=c2', 'top' );
    // directors is a custom post_type and should go to single-directors.php

    add_rewrite_rule( 'showreels/(.+?)/video/([^/]+)?/?$', 'index.php?category_name=$matches[1]&video=b', 'top' );
    // showreels is a custom post_type and should go to single-showreels.php

}
add_action( 'init', 'wpse13483_init' );

Any help appreciated!


UPDATES – this rule is now mostly working and catching the variables. However it is going to archive.php and not directors-single.php?

add_rewrite_rule( 'directors/(.+?)/showreels/([^/]*)/video/([^/]*)/?', 'index.php?post_type=directors&showreel=$matches[2]&video=$matches[3]', 'top' );
// directors is a custom post_type and should go to single-directors.php

i think its to do with the ‘?post_type=directors’ but can’t find any reference of what this should be to load single.php

UPDATE 2
Looking at Rewrite analyzeri think its missing the post_type variable?
rules

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

This seems to work!

?post_type=directors&name=$matches[1] seems to be the key

add_rewrite_rule( 'directors/([^/]*)/showreels/([^/]*)/video/([^/]*)/?', 'index.php?post_type=directors&name=$matches[1]&showreel=$matches[2]&video=$matches[3]', 'top' );

so final code now;

function wpse13483_init() {

    add_rewrite_rule( 'directors/([^/]*)/showreels/([^/]*)/video/([^/]*)/?', 'index.php?post_type=directors&name=$matches[1]&showreel=$matches[2]&video=$matches[3]', 'top' );

}
add_action( 'init', 'wpse13483_init' );

function wpa52794_query_vars( $vars) {
    $vars[] = 'video';
    $vars[] = 'showreel';

    return $vars;
}
add_filter( 'query_vars', 'wpa52794_query_vars' );

Method 2

WordPress will strip of query variables that it doesn’t understand by default. So in addition to registering your custom rewrite rules, you also have to register your custom query variables.

add_filter( 'query_vars', 'wpa52794_query_vars' );
function wpa52794_query_vars( $vars ) {
    $vars[] = 'video';
    $vars[] = 'showreel';

    return $vars;
}

Just to further complete the answer, you also need to specify the regular query variables WordPress is expecting. Your original example isn’t passing the post_type or anything to identify the post (ID, name, slug, etc) as you’ve already noted in your own comments. Without this, WordPress doesn’t understand how to route the request internally.

Kudos for discovering this with a rewrite analyzer. That was indeed the missing piece.

Method 3

In addition to @EAMann answer I can say that you need to flush rewrite rules.

@EAMann answer:

add_filter( 'query_vars', 'wpa52794_query_vars' );
function wpa52794_query_vars( $vars) {
    $vars[] = 'video';
    $vars[] = 'showreel';

    return $vars;
}

Flushing rewriting rules:

function myplugin_activation() {
    flush_rewrite_rules();
}
register_activation_hook ( __FILE__, 'myplugin_activation' );

function myplugin_deactivation() {
    flush_rewrite_rules();
}
register_deactivation_hook( __FILE__, 'myplugin_deactivation' );

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

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 Reply