Reputation: 11
Preface: I know this is an extremely common question. I've read about two dozen of these and tried all the proposed solutions, but just can't get it to work on my site. There are no other WordPress devs in my shop and I need more eyes on the code.
I am writing a custom WordPress block and need to be able to be able to rewrite URLs for SEO reasons. Specifically, when a browser hits a URL like:
mydomain.edu/url-rewrite-tester-post/foovar
the content that is served should be as if the URL were:
mydomain.edu/url-rewrite-tester-post?URLvar=foovar
More specifically, taking into account that the rewrite will not encounter certain default redirect rules to assume the index page, the rewrite should serve:
mydomain.edu/index.php?pagename=url-rewrite-tester-post&URLvar=foovar
IMPORTANT NOTE: The site's permalink structure is set to 'post name'. I've been able to get code of this kind working with a 'plain' permalink structure, but not with the 'post name' permalink structure in place.
This should be pretty simple, right? In the PHP file for my custom block I include the following:
function custom_block_url_rewrite() {
add_rewrite_rule('^url-rewrite-tester-post/([^/]+)/?$', 'index.php?pagename=url-rewrite-tester-post&URLvar=$matches[1]', 'top');
add_rewrite_tag('%URLvar%','([^/]+)');
}
add_action('init', 'custom_block_url_rewrite');
I save the permalink settings to refresh the buffer and the rule takes effect. Then I should be able to access the 'URLvar' variable with the following script included in the same PHP file:
function url_rewrite_test_url_rewrite_test_block_init($request_url) {
register_block_type( __DIR__ . '/build', array(
'render_callback' => function ($attributes, $request_url) {
$html_render_output = '';
if (isset($_GET['URLvar'])) {
$html_render_output .= 'You have fetched a URL variable using the GET method.<br>It is: ';
$html_render_output .= $_GET['URLvar'] . '<br><br>';
} else {
$html_render_output .= 'Could not fetch a URL variable via the GET method.<br>';
}
if (get_query_var('URLvar') != '') {
$URLvar = get_query_var('URLvar');
$html_render_output .= 'You have fetched a URL variable using the get_query_var method.<br>It is: ';
$html_render_output .= $URLvar . '<br><br>';
} else {
$html_render_output .= 'Unable to access a variable via the get_query_var method.<br>';
}
$html_render_output .= 'The URL at time of main function execution is: ' . $_SERVER['REQUEST_URI'] . '<br>';
return "$html_render_output";
}
));
}
add_action( 'init', 'url_rewrite_test_url_rewrite_test_block_init');
The $_GET method doesn't work, which I expect based on what I've read online. But the get_query_vars method should work!
By looking at the network tab in my browser's developer panel I can see that as soon as I try to hit a URL like 'http://mysite.local/url-rewrite-tester-post/foovar', I get a 301 redirect to 'http://mysite.local/url-rewrite-tester-post/'. That doesn't seem right! The code should rewrite, not redirect, right?
Additional layers to the mystery: If I try to hit a URL 'http://mysite.local/url-rewrite-tester-post/foovar' before implementing my rewrite rule, the site returns a 404 error.
I've tried accessing the query var using a method like:
$wp_query->query_vars['URLvar']
but I get a PHP error saying that query_vars has no key 'URLvar'.
I've tried making sure the URL rewrite rule is executed before the main function using the priority argument and by using various hooks that activate before 'init', such as 'muplugins_loaded' and 'setup_theme'. None of that changes the problem.
I'm running a local site using "Local" [https://localwp.com/], so I know there are no other rewrite or redirect rules in place causing this problem.
The only lead I haven't exhausted so far is the comment by bcworks on the add_rewrite_tag documentation page [https://developer.wordpress.org/reference/functions/add_rewrite_tag/]. I'm not 100% clear on how to implement his suggestion. Is that going to be my golden bullet?
Upvotes: 0
Views: 125
Reputation: 11
Welp, I cracked it. I was testing the block in posts, not on pages. URL rewriting works for proper pages only, not posts or the pseudo-pages where you preview individual posts. Bleh. So much time lost to this.
Upvotes: 0