How can you handle rewrite rules for custom post types with option to filter on custom taxonomy terms?

This is what I’ve used in the past for a similar requirement;

register_post_type('movie', array(
    'rewrite' => array('slug' => 'movie')
));

register_taxonomy('movie_location', 'movie', array(
    'rewrite' => array('slug' => 'movies')
));

/**
 * Add rewrite rules for 'base' archives.
 * @param object $r Instance of {@see WP_Rewrite}
 */
function my_custom_rewrite_rules(&$r)
{
    $rules = array(
        'movies/page/?([0-9]{1,})/?$' => 'post_type=movie&paged=' . $r->preg_index(1),
        'movies/?$' => 'post_type=movie'
    );

    foreach ($rules as &$rule)
        $rule = $r->index . '?' . $rule;
    $r->rules = array_merge($rules, $r->rules);
}
add_action('generate_rewrite_rules', 'my_custom_rewrite_rules');

See the rewrite argument in register_taxonomy()? WordPress automatically creates the appropriate rewrite rules, including archive pagination!

Also note the singular use of movie in the register_post_type() rewrite argument – partly because, IMO, it’s semantically correct, but more so that you don’t open up a whole can of worms.

What’s that can of worms exactly?

Well, otherwise you’ll end up with two rewrite rules like so;

'movies/([^/]+)/?$' => 'post_type=movie&movie_location=$matches[1]'
'movies/([^/]+)/?$' => 'post_type=movie&name=$matches[1]'

Whichever one is indexed first in the rewrite rules array will always be triggered, and the other one ignored.

So say you’ve a got a movie named made-in-britain, but the rewrite rule for the taxonomy archive comes first, WordPress is always gonna look for movies with the made-in-britain term, rather than the movie itself!