If you don’t want to use add_feed()
, then you can use add_rewrite_rule()
:
add_action( 'init', function () {
add_rewrite_rule(
'^feed/(schedule|calendar)/?$',
'index.php?feed=$matches[1]',
'top'
);
} );
add_action( 'do_feed_schedule', function () {
header( 'Content-Type: text/plain' ); // dummy type just for testing
echo 'Yay, it works!';
} );
But regarding the original question about add_feed()
..
Why would WordPress overwrite existing page rules with the feed,
instead of just using only the/feed/
base as expected?
So that example.com/schedule
would serve your custom feed, just like standard feed URLs such as example.com/feed
. But WordPress does create the (proper) rules having the feed/
base for custom feed URLs like example.com/feed/schedule
.
Therefore you shouldn’t use schedule
as the slug of your Page, or if you have/need to, then you can alter the feed rewrite so that the example.com/schedule
will serve the Page instead of your feed:
-
If you know the exact rule/RegEx:
add_filter( 'rewrite_rules_array', function ( $rules ) { $rules2 = []; foreach ( $rules as $regex => $query ) { if ( '(feed|rdf|rss|rss2|atom|schedule)/?$' === $regex ) { // it has 'schedule' $rules2['(feed|rdf|rss|rss2|atom)/?$'] = $query; // so let's remove it } else { $rules2[ $regex ] = $query; } } return $rules2; } );
-
Otherwise, try something dynamic like this:
add_filter( 'rewrite_rules_array', function ( $rules ) { global $wp_rewrite; $feeds = $wp_rewrite->feeds; // original feeds $pages = [ 'schedule', 'calendar' ]; // page slugs list $feeds2 = array_diff( $feeds, $pages ); $rules2 = []; $feeds = implode( '|', $feeds ); $feeds2 = implode( '|', $feeds2 ); foreach ( $rules as $regex => $query ) { if ( '(' . $feeds . ')/?$' === $regex ) { $rules2[ '(' . $feeds2 . ')/?$' ] = $query; } else { $rules2[ $regex ] = $query; } } return $rules2; } );
Note that I use the foreach
so that the rule stays in its original position. And another possible option is that just move the rule to a position after the Page rewrite rules. But I haven’t yet tried that and the above code should be enough as a workaround..
And if I’m not mistaken, here’s the code which WordPress use to generate the rule that’s being altered in the above function:
// Create query for /(feed|atom|rss|rss2|rdf) (see comment near creation of $feedregex).
$feedmatch2 = $match . $feedregex2;
$feedquery2 = $feedindex . '?' . $query . '&feed=' . $this->preg_index( $num_toks + 1 );
See the source on Trac.