You have the right idea, but the specific details are off. Please refer to the add_rewrite_rule() docs. From the examples, “init” is a more appropriate action to hook. Rewrites should be constructed to go through index.php with all needed query vars specified as URL parameters. Thus you need the events post type specified as well as the event slug itself. Your regexp should be more like this: '^webinars/([^/]+)/?' You match the incoming request, not what it should have been. The regexp should be able to match any legal URL for the event, including a possible trailing slash
Once you’ve made these adjustments, be sure you visit the permalink settings page to force the rules to be regenerated. There’s no need to change anything, just visiting is enough.
I changed my code to this but it still doesn’t work:
add_action( 'init', 'webinar_rewrite_rule', 20);
function webinar_rewrite_rule() {
add_rewrite_rule( '^webinars/([^/]+)/?', 'index.php?tribe_events=$matches[1]&post_type=tribe_events', 'top' );
}
Is there something else I need to add? After I uploaded this code I did flush the rewrite rules by going to the Permalinks setting page and clicking on Save Changes without changing anything.
Hmmm. That should do it, it looks good. I even tried your code on my site, which also has custom post types and taxonomies. The only adjustments I made was the post type and taxonomy slugs. Requesting example.com/webinars/term-slug/ resulted in a list of my CPTs that have the requested term assigned.
Do you really have a taxonomy using the same slug as a custom post type (tribe_events)? If not there’s the problem. Otherwise, does the taxonomy have a different permalink base? Maybe try using the base as an URL parameter instead of the taxonomy slug? No idea if that would work.
I don’t think taxonomies and post types sharing a common slug is generally a good idea. If it’s not too onerous to do so, I recommend changing one or the other. If that’s out of the question, and the permalink base idea didn’t work, we can force it to work (or pick any other base term that’s not used elsewhere). Whitelist this base by adding it through the “query_vars” filter. Then in a “pre_get_posts” callback, any time this base occurs, get the value for it and construct or add to the “tax_query” argument array so it specifies the value as the “terms” argument in the array for tribe_events tax queries. This establishes an alias for the taxonomy so there is no ambiguity.
I got the rewrite function to work finally. I changed the priority from 20 to 5 and it worked, like so add_action( 'init', 'webinar_rewrite_rule', 5);
The function to change the permalinks still doesn’t work. Is it because I’m using the wrong hook (post_link)?
Ah! An inspired idea pays off 🙂 I cannot explain why that would work, it seems like the rule would be pushed further down and be less likely to be applied before something else takes precedence. My logic appears to be backwards, I’m missing something about how this is supposed to work.
No matter, solution found. I’m sorry, I didn’t realize the permalink was also a problem. Yes, “post_link” only applies to actual “post” post types. It’s not very well documented. For CPTs you should use “post_type_link”.
Also, you add your callback by specifying 3 parameters be passed, but your callback declaration only collects 2. “post_type_link” passes 4 parameters, but the first 2 are all you really need. Changing the add_filter() call ought to do it:
add_filter( 'post_type_link', 'change_webinar_links', 10, 2 );
I got the permalink function to work too. Here’s my complete working code for those in a similar situation. The ‘tribe_event_in_category’ function is a built-in function of the Events Calendar plugin.
add_filter( 'post_type_link', 'change_webinar_links', 10, 2 );
function change_webinar_links( $link, $post) {
if ( $post->post_type == 'tribe_events' && tribe_event_in_category('webinar') ) {
$link = trailingslashit( home_url('/webinars/' . $post->post_name ) );
}
return $link;
}
add_action( 'init', 'webinar_rewrite_rule', 5);
function webinar_rewrite_rule() {
add_rewrite_rule( '^webinars/([^/]+)/?', 'index.php?tribe_events=$matches[1]&post_type=tribe_events&name=$matches[1]', 'top' );
}
Thank you so much bcworkz for your help.