3

In my theme (a child of Twenty Sixteen) I've created a new Custom Post Type, pg_review. I've associated two custom taxonomies with it, pg_genres (hierarchical categories), and pg_authors (like tags).

Everything is working fine except permalinks... Despite trying to understand and adapt various examples I'm going round in circles.

I would like these permalinks to work:

/reading/2017/02/19/post-name/  # A single Review.
/reading/2017/02/19/            # Reviews from one day.
/reading/2017/02/               # Reviews from one month.
/reading/2017/                  # Reviews from one year
/reading/                       # The most recent Reviews (this is working).
/reading/genre/genre-name/      # Reviews in a `pg_genre`.
/reading/author/author-name/    # Reviews in a `pg_author'.

This is pretty much how conventional Posts work if given a custom permalink structure like /archive/%year%/%monthnum%/%day%/%postname%/. But how do I make this work for a Custom Post Type?

(I've tried the Custom Post Type Permalinks plugin which promises to do this, but the links for taxonomies 404 (a problem others in support seem to have too).)

1
  • Here's an article that provides a copypasta class where you can just replace their values with your own to get your custom post working. It also explains the various parts of the code in pretty detailed manner: blog.terresquall.com/2021/03/…
    – John Doe
    Apr 1, 2021 at 10:28

1 Answer 1

5

We'll start with the taxonomies, as those are fairly simple. If you register those with simply reading/genre and reading/author as the slug argument, those should work without issue.

The post type is a bit more tricky. For that, we register with the rewrite argument set to just true. Then we add a new permastruct for that post type with:

add_permastruct(
    'pg_review',
    "/reading/%year%/%monthnum%/%day%/%pg_review%/",
    array( 'with_front' => false )
);

We'll now have the rules for single post views, but the year/month/day views will all have the wrong post type set, so we'll add some new rules to reset those with:

add_rewrite_rule(
    '^reading/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/?$',
    'index.php?post_type=pg_review&year=$matches[1]&monthnum=$matches[2]&day=$matches[3]',
    'top'
);
add_rewrite_rule(
    '^reading/([0-9]{4})/([0-9]{1,2})/?$',
    'index.php?post_type=pg_review&year=$matches[1]&monthnum=$matches[2]',
    'top'
);
add_rewrite_rule(
    '^reading/([0-9]{4})/?$',
    'index.php?post_type=pg_review&year=$matches[1]',
    'top'
);

The last step is to filter post_type_link to insert the correct year/month/day in the permalinks:

function wpd_pg_review_permalinks( $url, $post ) {
    if ( 'pg_review' == get_post_type( $post ) ) {
        $url = str_replace( "%year%", get_the_date('Y'), $url );
        $url = str_replace( "%monthnum%", get_the_date('m'), $url );
        $url = str_replace( "%day%", get_the_date('d'), $url );
    }
    return $url;
}
add_filter( 'post_type_link', 'wpd_pg_review_permalinks', 10, 2 );
8
  • Wow, thanks for this Milo, so helpful! Nearly there... On the post type I had to keep 'rewrite' => array( 'slug' => 'reading', 'with_front' => false,) in order for the /reading/ page to keep working. I had to add another add_rewrite_rule() to match the full /reading/yyyy/mm/dd/name/ path for a single review. And when filtering post_type_link add $url = str_replace( "%reading%", $post->post_name, $url );. Feb 20, 2017 at 9:51
  • The only thing that's not quite right is the taxonomies' URLs are like /blog/reading/genre/[name]/ and /blog/reading/author/[name]/ I can't work out how to get rid of the /blog from the start - that's used for all the standard WP Posts. I've tried the taxonomies' rewrites having both 'with_front'=>'false' and without, but no difference. Feb 20, 2017 at 9:55
  • 'false' is a string and evaluates to true, it should be 'with_front' => false without quotes.
    – Milo
    Feb 20, 2017 at 16:24
  • Doh, of course, well spotted Milo! The taxonomies' links are now correct! However, I've spotted that the year/month/day archives, like /reading/2017/, only show Posts, not my custom pg_review post types. Feb 20, 2017 at 16:30
  • /reading/2017/ shows standard Posts from that year, but /reading/2017/?post_type=pg_review does show Reviews. Feb 20, 2017 at 16:35

Your Answer

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

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