If you haven’t already done so, I suggest you to check out this Codex article which gives a good introduction on how you can use add_rewrite_rule()
to rewrite a URL in WordPress.
Now if the news
and single
are Pages (i.e. posts of the page
type) and that single
is a child of the news
Page, then in the second parameter for add_rewrite_rule()
(i.e. the redirect URL), you would want to use pagename=news/single
which will load the single
Page.
Alternatively, you can use page_id=<ID>
to query the Page by its ID instead.
See the WP_Query
class for more details regarding pagename
and page_id
.
Then you would also want to use a custom query arg for the single news ID because for example you wouldn’t be able to retrieve the ID using $_GET['id']
. And then you should add the custom arg to the public query args which WordPress reads from the URL and pass them to WP_Query
.
So having said that, try the following:
// Register the custom rewrite rule.
function wpse_373628_init() {
add_rewrite_rule(
// Matches /news/<id>/<title-slug> in the URL.
'^news/(\d+)/([^/]+)/?$',
// You could also add &news_title=$matches[2], but I think the ID is
// enough for you to identify the single news being requested.
'index.php?pagename=news/single&news_id=$matches[1]', // query by slug
// 'index.php?page_id=123&news_id=$matches[1]', // or query by ID
'top'
);
}
add_action( 'init', 'wpse_373628_init' );
// And register the custom query arg.
function wpse_373628_query_vars( $vars ) {
$vars[] = 'news_id';
// $vars[] = 'news_title'; // if you're using news_title in the rewrite rule
return $vars;
}
add_filter( 'query_vars', 'wpse_373628_query_vars' );
And be sure to flush the rewrite rules by simply visiting the permalink settings page (wp-admin
» Permalink Settings) so that WordPress recognizes the new rewrite rule (above) and saves it in the database.
And also, to retrieve the news ID, you can use get_query_var( 'news_id' )
.