1

I'm having troubles understanding how add_rewrite_rule works in my case. I have a page which lists news from an external source. All items are linked with a "read more". Those links look like: domain.com/news/single/?id=12345&title=title-of-this-news

Everything works fine. If I click the link the "single" page reads the "id" param and displays the output I want it to.

Well to make this pretty I want the links to look like this: domain.com/news/12345/title-of-this-news which means /single/ not part of the url - the first part is the ID I need to fetch it's data and the title the last part.

Can someone help me with this? Thanks!

EDIT: due to one of the answers I came up with this to match my URL, params, and so on - but it is not working (permalinks are resaved):

// Register the custom rewrite rule.
function wpse_373628_init() {
    add_rewrite_rule(
        // Matches /news/<id>/<title-slug> in the URL.
        '^news-events/single/(\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-events/single&newsID=$matches[1]&newsTitle=$matches[2]', // 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[] = 'newsID';
    $vars[] = 'newsTitle'; // if you're using news_title in the rewrite rule
    return $vars;
}
add_filter( 'query_vars', 'wpse_373628_query_vars' );
4
  • What are the single and news? Are they Pages, i.e. posts of the page type? Also, if the pretty URL doesn't include the id, then would you still be able to identify what the single news feed is based solely on the title (e.g. the title-of-this-news)?
    – Sally CJ
    Aug 25, 2020 at 2:42
  • @SallyCJ /news/ = list view: /single/ = single view. this pages are page types. I need the ID param for the single view to fetch all its news data via a JSON feed. this all works. I just want to make the url pretty. no unfortunately it can not access the single news data with only the title, I need the ID parsed as param. Does it make a difference?
    – ggzone
    Aug 25, 2020 at 7:20
  • 1
    If the ID is required to display the correct content then it needs to be in the URL. You can't hide it entirely unless it's possible to retrieve the ID from the title. Aug 25, 2020 at 15:25
  • @JacobPeattie i see. thank you! I'll update my question
    – ggzone
    Aug 26, 2020 at 8:45

1 Answer 1

1

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' ).

4
  • thanks! - that helped me a lot. I made some adjustments because the page name changed and the params as well; and I edited my question. May you take another look at the code I posted and give me feedback where the issue is maybe?
    – ggzone
    Sep 14, 2020 at 8:27
  • Your code worked fine for me, but you need to make sure the Pages news-events and single both exist, and use get_query_var() to get the newsID or newsTitle value. And did you visit example.com/news-events/single/<news ID>/<news title> (e.g. example.com/news-events/single/123/foo-bar) or another URL? Also, what exactly is not working — you got a 404 error, you see a different page, or?
    – Sally CJ
    Sep 15, 2020 at 1:53
  • thanks u guys, it works. I thought a link with params would automatically redirect or resolve to the pretty url but it doesn't. I changed the link to the single view to the pretty one with the rewrite rule active (and permalinks resaved) and used the get_query_var func to read the ID
    – ggzone
    Sep 21, 2020 at 11:51
  • That redirect can be achieved, but it's not part of the original question, hence I didn't include that part.. But anyway, I'm glad the answer helped. :)
    – Sally CJ
    Sep 21, 2020 at 17:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.