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 Answer
1

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

Leave a Reply

Your email address will not be published. Required fields are marked *