OK, let's first get some definitive clarification on the proper query vars.
Refer to Post and Page parameters on the WP_Query
codex page.
name (string) - use post slug.
pagename (string) - use page slug.
We can confirm this with WP_Query
:
$args = array(
'name' => 'mypage'
);
$mypage = new WP_Query( $args );
echo '<pre>';
print_r( $mypage );
echo '</pre>';
which will produce:
SELECT wp_posts.*
FROM wp_posts
WHERE 1=1
AND wp_posts.post_name = 'mypage'
AND wp_posts.post_type = 'post'
ORDER BY wp_posts.post_date DESC
It's looking for mypage
slug in the post
post type. If we change this to pagename
, it looks in the page
post type.
The reason it kind of works on the main query with name
is due to the redirect_guess_404_permalink
function, which kicks in when the original request is a 404. It runs another query to find the closest match and redirect there, if something is found. This also results in any extra parameters getting stripped from the URL.
One important thing to note with hierarchical post types- if your page is a child of another page, you must set the pagename
query var with the parent/child
path, as different parents can have children with the same slug.
As for your question, changing the query var to pagename
works with your original code in v4.7.2 and the Twenty Sixteen theme:
function wpd_mypage_rewrite() {
add_rewrite_tag(
'%mycustomvar%',
'([^/]+)'
);
add_rewrite_rule(
'^mypage/([^/]+)/?',
'index.php?pagename=mypage&mycustomvar=$matches[1]',
'top'
);
}
add_action( 'init', 'wpd_mypage_rewrite' );
Note that I used add_rewrite_tag
here. You could instead use the query_vars
filter. The reason add_rewrite_tag
works is that it internally adds the query var via the same filter.
Don't forget to flush rewrite rules after adding / changing rules. You can also do this by visiting the Settings > Permalinks page.
You can then echo get_query_var( 'mycustomvar' );
in the template, and the value is output.
name
is the query var for post typepost
,pagename
is for post typepage
.name
worked better, at least for the first variable...name
, it rewrote at least the first part of my url correctly, whereas usingpagename
it did not.name
, because that query is failing, and WP is querying for any post type that matchesmypage
, and redirecting there. Rewrite rules just match requests against rules and convert them to query vars, outputting that rewritten URL is a separate and unrelated task.