0

I have a custom post type "events" that has rewrites / permalink modification in place so that it includes the year and month in the URL (these come from ACF fields). This works perfectly BUT if we have 2 events using the same "slug" then WordPress forces the new one to have a unique postname / slug. I've tried Googling this for a bit too long but can't really find a fix for this.

Example of what is happening (where 'saint-louis' is the postname / slug taken from the title):

https://example.com/events/2022/january/saint-louis/

https://example.com/events/2022/february/saint-louis-2/

What I would like to see:

https://example.com/events/2022/january/saint-louis/

https://example.com/events/2022/february/saint-louis/

The closest I got to a fix would be perhaps removing the postname entirely: Custom post type permalink: only use %post_id% and remove %postname%

However: that fix includes the post ID, which I don't want in the URL. Does anyone have any ideas here? I've also considered using another custom field (for 'city') so that 'saint-louis' wouldn't be pulling from the postname, but I don't really know where to start there.

I've also attempted to turn hierarchy on / off and the capability to "page" but have had no luck.

My setup currently:

function wdacRegisterEventsPostType() {

/**
 * Post Type: Events.
 */

add_rewrite_tag( '%wdac_year%', '([^&]+)' );
add_rewrite_tag( '%wdac_month%', '([^&]+)' );

$labels = [
    "name" => __( "Events", "wdac" ),
    "singular_name" => __( "Event", "wdac" ),
];

$args = [
    "label" => __( "Events", "wdac" ),
    "labels" => $labels,
    "description" => "",
    "public" => true,
    "publicly_queryable" => true,
    "show_ui" => true,
    "show_in_rest" => false,
    "rest_base" => "",
    "rest_controller_class" => "WP_REST_Posts_Controller",
    "has_archive" => 'events',
    "show_in_menu" => true,
    "show_in_nav_menus" => true,
    "delete_with_user" => false,
    "exclude_from_search" => false,
    "capability_type" => "post",
    "map_meta_cap" => true,
    "hierarchical" => false,
    "rewrite" => [
        "slug" => "/events/%wdac_year%/%wdac_month%",
        "with_front" => false
    ],
    "query_var" => true,
    "menu_position" => 5,
    "menu_icon" => "dashicons-calendar-alt",
    "supports" => [ "title", "editor", "thumbnail" ],
];

register_post_type( "events", $args );
}
add_action( 'init', 'wdacRegisterEventsPostType' );


// Modify events permalink
function wdacModifyEventsURL($permalink, $post) {
$yearMask = '%wdac_year%';
$monthMask = '%wdac_month%';

// Exit early.
if( strpos($permalink, $yearMask) === false && strpos($permalink, $monthMask) === false ) {
    return $permalink;
}

// Another exit early
if (!function_exists('get_field')) {
    return $permalink;
}

$startDate = strtotime(get_field('wdac_event_start_date', $post->ID));

$year = date("Y", $startDate);
$month = strtolower(date("F", $startDate));

return str_replace([$yearMask,$monthMask], [$year, $month], $permalink );
}
add_filter('post_type_link', 'wdacModifyEventsURL', 1, 3);
4
  • If you go to https://example.com/events/2022/february/saint-louis/ does it redirect you somewhere?
    – kero
    Jan 19 at 18:44
  • @kero no it does not. It loads the January event and ignores the stuff in front of the postname.
    – EmilyH
    Jan 19 at 18:49
  • 1
    the full permalink might be unique but the slug is not and is occupied by whatever is sitting at events/2022/january/saint-louis/ because saint-louis is the important part that gets checked, not events/2022/january
    – Tom J Nowell
    Jan 19 at 20:01
  • @TomJNowell any idea for getting that to be part of the unique "check" that wp does? Maybe a rewrite?
    – EmilyH
    Jan 19 at 20:21

1 Answer 1

1

By default, WordPress disallow 2 identical slugs because if you change your permalink structure for custom structure, you should be able to have in your case:

And you can understand, it's impossible.

The only way is checking by code, you are not in "custom structure" and then save in db with the WordPress method (adding "-2") and then add a rewrite rule, or find a proper hook to remove it before use in front-end.

1
  • Appreciate the response; that's kind of what I figured.
    – EmilyH
    Jan 20 at 19:07

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.