Seems like a good candidate for add_rewrite_endpoint()
.
add_rewrite_endpoint( 'items', EP_ROOT, 'item_id' );
That will register the endpoint /items/<item ID>
and also registers the query var item_id
, and eliminates the 404 status header/title as well. But the page title would be the site name and you’d probably still want to hook to pre_get_document_title
to customize the title.
And your class would be simpler:
class FeedPlugin {
public function __construct() {
add_action( 'init', [ $this, 'add_rewrite_endpoint' ] );
add_action( 'template_redirect', [ $this, 'addTemplate' ] );
}
public function add_rewrite_endpoint() {
add_rewrite_endpoint( 'items', EP_ROOT, 'item_id' );
}
public function addTemplate() {
if ( $item_id = get_query_var( 'item_id' ) ) {
/* your code here:
echo 'Yay, it works! Item ID: ' . $item_id;
exit;
*/
}
}
}
Don’t forget to flush the rewrite rules — just visit the permalink settings page.
UPDATE
how can I specify what is valid for
release_id
e.g[0-9A-Z]+
So I believe you meant item_id
when you said release_id
?
And (at the moment) there’s no “standard”/easy way to specify the preferred RegEx pattern for an endpoint added using add_rewrite_endpoint()
, so if you need a custom RegEx pattern, it’s actually better to use add_rewrite_rule()
. 🙂
And here’s how you can prevent the 404 error with your original code.
I believe you know it happens because you’re querying a post/Page that doesn’t exist (pagename=items
) and I also believe you added that in the rewrite rule as an identifier for the custom feed request.
And I’m not sure if you intentionally didn’t do this, but it’s a very easy way to prevent the 404 error: create a Page and set its slug to items
.
That may sound silly, but it actually works. (Although you’d still need to tweak the page title.) And you could just create a custom Page template (which loads/generates/renders the feed) and assign the template to that items
Page, without having to hook to template_redirect
.
Alternate solution without creating a Page
-
In the
addRewriteRules()
, just omit thepagename=items&
:public function addRewriteRules() { add_rewrite_rule( 'items/([0-9]+)/?$', 'index.php?item_id=$matches[1]', 'top' ); }
-
In the
addTemplate()
, check if the matched rewrite rule is the one you added viaadd_rewrite_rule()
above:public function addTemplate() { global $item, $wp; if ( 'items/([0-9]+)/?$' === $wp->matched_rule && ( $item_id = get_query_var('item_id') ) ) { // your code here } }
But once again, you’d still need to tweak the page title which defaults to the site name.