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 the pagename=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 via add_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.