1

I posted this in stackoverflow as well, so hope it's good to post here as well!

I think this is my last problem to solve before everything clicks into place:

I have a homepage with a custom plugin that sends some data to another page, I am building a theme for this website that works with the plugin.

So in the theme functions.php I have added a

function myvar($vars){
    $vars[] = 'ep_year';
    $vars[] = 'ep_name';
    return $vars;
}
add_filter('query_vars','myvar');

works a charm, I can send those values over to a custom page with a custom template assigned. This has a permalink as follows:

http://ngofwp.local/episode/

and when I send the data over it looks like so (permalinks are enabled):

http://ngofwp.local/episode/?ep_year=2011&ep_name=silly_donkey

I know I have to use an add_rewrite_rule so I've started coding that as follows:

function custom_rewrite_rule()
    {
        add_rewrite_rule('^episode/([^/]*)/([^/]*)\.html$','?ep_year=$matches[1]&ep_name=$matches[2]','top');
    }
add_action('init', 'custom_rewrite_rule');

But now for the life of me I have no clue about the formulae to get it to work. I have read the regex rules and tested that particular rewrite on a site that helps you do that.

What I'd like it to look like is this:

http://ngofwp.local/episode/2011/silly_donkey.html

The

http://ngofwp.local/episode/

is given by wordpress's permalink setting and is a custom page in the templates folder (it displays correctly)

What did I do wrong?

6
  • you did nothing wrong, its your expectations that are wrong, nothing in your code has changed the permalinks, you've just told WP that a rewrite rule exists that maps this regex to those query variables, then expected that it would put 2 and 2 together and figure out that you also wanted the permalinks to change but that's a leap of faith/logical jump. Not to mention that permalinks are for terms and posts, but that's not what your rewrite rule is for. And what's the specific problem? Is it that your rewrite rule finds nothing? Doesn't load your page template? Wrong canonical URL?
    – Tom J Nowell
    Commented Feb 16, 2023 at 11:10
  • To fix this you'll need to provide significantly more information about how your page works, how the template is loaded, etc, and what exactly is it showing, is it an archive for a custom database table? A custom view of a CPT? A filter? Also be very very wary of posting the same question multiple times, especially on the same stack, not all the moderation here is by humans, a lot of it is automated
    – Tom J Nowell
    Commented Feb 16, 2023 at 11:12
  • I'll try my best to provide more information: I have made a plugin to store all podcast episodes in a custom table. Then I am making a custom theme to use where in the main index file there are all the episodes. (currently that works) Then you click on an episode and it goes to that page with the player and shownotes. Currently the homepage passes the variables correctly to that page via querystring (so I will be able to load the relevant data), but it's not pretty - so on a second thought it is for beautifyng the URL.
    – johnbell
    Commented Feb 16, 2023 at 14:41
  • The episode page is a page created in wordpress that has a custom template applied (/* Template Name: Episode Player */) ; in there I receive the variables, but the url is as mentioned in the main post
    – johnbell
    Commented Feb 16, 2023 at 14:43
  • So what I'm thinking now is I just need a url re-write in htaccess.
    – johnbell
    Commented Feb 16, 2023 at 14:45

2 Answers 2

2

It looks like your add_rewrite_rule function is not quite correct. The first parameter should be the regular expression pattern that you want to match, and the second parameter should be the query string that you want to rewrite the URL to. Also, you don't need to include the file extension in the URL.

Try updating your custom_rewrite_rule function to this:

function custom_rewrite_rule() {
    add_rewrite_rule('^episode/([^/]*)/([^/]*)/?$','index.php?page_id=PAGE_ID&ep_year=$matches[1]&ep_name=$matches[2]','top');
}
add_action('init', 'custom_rewrite_rule');

Replace PAGE_ID with the ID of the page that displays the custom template for your /episode/ URL. You can find the page ID by editing the page in WordPress and looking at the URL in your browser's address bar - it will be something like post.php?post=PAGE_ID&action=edit.

This rule will match a URL like http://ngofwp.local/episode/2011/silly_donkey/ and rewrite it to http://ngofwp.local/index.php?page_id=PAGE_ID&ep_year=2011&ep_name=silly_donkey.

After updating the functions.php file, you'll need to go to the WordPress dashboard Settings > Permalinks and click the "Save Changes" button to flush the rewrite rules cache and make your new rule active.

3
  • Thanks EVER SO MUCH, this has been bugging me for 2 days now!!! I just tried that and it worked!!! I would give you a (manly) hug right now!
    – johnbell
    Commented Feb 16, 2023 at 22:58
  • I was just wondering if this can be done without the ID that naturally changes for every wordpress installation, is there a way?
    – johnbell
    Commented Feb 24, 2023 at 18:39
  • Thanks. You saved the day. Commented Aug 22 at 18:42
1

What I suspect has happened is that you're using this to hide the ugly URL variables and turn them into pretty URLs via regex, and you've almost done that part correctly:

?ep_year=$matches[1]&ep_name=$matches[2]

But nothing in that tells WordPress which page you wanted. How is it meant to know it should be the episode page?

To fix this it will need to explicitly tell WP this, perhaps with something like this:

?ep_year=$matches[1]&ep_name=$matches[2]&pagename=episode

Then on top of that, the regex maps to the wrong URL, ugly permalinks always take the form index.php followed by URL parameters. This is the reason why WP rewrite rules can't map URLs on to arbitrary files. So it needs to instead map to:

index.php?ep_year=$matches[1]&ep_name=$matches[2]&pagename=episode

The other issue it will have is that because it uses a custom page template the header tags will be set up for a singular piece of content, not an archive. This also means WP might decide to redirect to what it thinks is the canonical URL, and it also means everything under /episode has the canonical URL or /episode, which is true and correct. You might have intended this to be an archive of episodes with individual episodes accessible via a rewrite, but you've only built the appearance of such an archive. It will need to filter these to fix that.

To truly do this correctly though, it needs a CPT for each episode, custom permalinks, and a filter to modify each episodes post URL to add the correct year.

Note that for any of this to work:

  • pretty permalinks have to be enabled in settings
  • you have to flush permalinks/rewrite rules whenever you change the rewrite rules, visiting the permalinks settings page is enough to do this
  • use get_query_var not $_GET in your template
  • your URL must match the regex, it should show as a match in WP debugging plugins too
13
  • 1
    If @johnbell was referring to a Page (post type page) with the slug episode, then the query var is pagename, so, pagename=episode. He should also use index.php? instead of just ?. Otherwise, even with the correct query vars, the permalink won't work.
    – Sally CJ
    Commented Feb 16, 2023 at 11:35
  • 1
    nice catch! Updated
    – Tom J Nowell
    Commented Feb 16, 2023 at 11:49
  • Thanks, I have tried amending as per your suggestion however still it's a no go. nothing really happens. This is a podcast website that has several episodes so I can't really create a page for each episode as they are all the same (conceptually) with small variations. Do I have to have permalinks enabled for this to work? Funny thing is those rewrite rules don't even show up in the Rewrite Analyser. But the idea is that I actually execute the query with the get vars that are passed on to the url so it's not just a 'beauty' thing.
    – johnbell
    Commented Feb 16, 2023 at 14:34
  • when you say nothing really happens can you be more specific? And did you flush permalinks after the changes? The rule should show up in rewrite analyser plugins, and yes pretty permalinks must be enabled to use rewrite rules ( because pretty permalinks are rewrite rules ). You also have to use get_query_var to grab the values. Also where is the custom_rewrite_rule function located? I assumed it was in a plugin or functions.php
    – Tom J Nowell
    Commented Feb 16, 2023 at 14:46
  • what I mean is that the url doesn't get re-written. If I test the page by going at "ngofwp.local/episode/2020/blue" it goes to the 404 page. If I test the page by going at "ngofwp.local/episode/?ep_year=2020&ep_name=blue" it goes to the correct template and vars are passed successfully (yes I am using get_query_var) The custom_rewrite_rule is in the functions.php of the theme.
    – johnbell
    Commented Feb 16, 2023 at 14:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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