1

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

2

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 );
  • 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 );. – Phil Gyford Feb 20 '17 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. – Phil Gyford Feb 20 '17 at 9:55
  • 'false' is a string and evaluates to true, it should be 'with_front' => false without quotes. – Milo Feb 20 '17 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. – Phil Gyford Feb 20 '17 at 16:30
  • /reading/2017/ shows standard Posts from that year, but /reading/2017/?post_type=pg_review does show Reviews. – Phil Gyford Feb 20 '17 at 16:35

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.