I’ve generated three different custom post types (e.g. books, movies, games). I’ve also created a custom taxonomy for all of them (e.g. genre).
What I need are archives for the taxonomy based on the post types. For example: “books-genre”, “movies-genre”…
Is there any solution to do that? Now I’ve only the taxonomy archive for “genre”.
Here is a complete example made possible using add_rewrite_rule()
. The basic setup for this example is documented first, then we’ll get to the real part of the solution using add_rewrite_rule()
.
Taxonomy and Post Type registration
Register the genre
taxonomy and the book
, movie
, and game
post types (note that the singular version of each of these names is being used in this example because it’s considered a best practice).
// Create taxonomy: genre for post types: book, movie, and game
// https://codex.wordpress.org/Function_Reference/register_taxonomy
add_action( 'init', 'wpse247013_register_taxonomies', 0 );
function wpse247013_register_taxonomies() {
$args = [
'public' => true,
'hierarchical' => false,
'label' => __( 'Genres', 'textdomain' ),
'show_ui' => true,
'show_admin_column' => true,
'query_var' => 'genre',
'rewrite' => [ 'slug' => 'genres' ],
];
register_taxonomy( 'genre', [ 'book', 'movie', 'game' ], $args );
}
// Create post types: movie, book, and game
// https://developer.wordpress.org/reference/functions/register_post_type/
add_action( 'init', 'wpse247013_register_post_types' );
function wpse247013_register_post_types() {
$book_args = [
'label' => __( 'Books', 'textdomain' ),
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => [ 'slug' => 'books' ],
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => null,
'supports' => [ 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ],
'taxonomies' => [ 'genre' ],
];
register_post_type( 'book', $book_args );
$movie_args = [
'label' => __( 'Movies', 'textdomain' ),
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => [ 'slug' => 'movies' ],
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => null,
'supports' => [ 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ],
'taxonomies' => [ 'genre' ],
];
register_post_type( 'movie', $movie_args );
$game_args = [
'label' => __( 'Games', 'textdomain' ),
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => [ 'slug' => 'games' ],
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => null,
'supports' => [ 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ],
'taxonomies' => [ 'genre' ],
];
register_post_type( 'game', $game_args );
}
Basic URL Examples
Based on the setup above, we’ll get these URLs out of the box:
Post type archive URLs
- http://example.com/books/
- http://example.com/movies/
- http://example.com/games/
Single post type URLs
- http://example.com/books/{book-post-slug}
- http://example.com/movies/{movie-post-slug}
- http://example.com/games/{game-post-slug}
Taxonomy Term archive URLs
- http://example.com/genres/{genre-term-slug}
(this archive will include all post types, which is not what we’re after)
Handle rewrite rules
Rewrite rules must be added in order to limit a particular genre term to a single post type. An additional rule is needed for pagination for each post type.
/**
* Add rewrite rules for genre terms limited to book, movie, and game post types.
* Pagination issue fix via http://wordpress.stackexchange.com/a/23155/2807
* @link https://codex.wordpress.org/Rewrite_API/add_rewrite_rule
*/
function wpse247013_rewrite_rules() {
// Book Genres
add_rewrite_rule( '^books/book-genres/([^/]+)/?$',
'index.php?taxonomy=genre&post_type=book&term=$matches[1]', 'top' );
// Book Genres pagination
add_rewrite_rule( '^books/book-genres/([^/]+)/page/([0-9]+)?$',
'index.php?post_type=book&genre=$matches[1]&paged=$matches[2]', 'top' );
// Movie Genres
add_rewrite_rule( '^movies/movie-genres/([^/]+)/?$',
'index.php?taxonomy=genre&post_type=movie&term=$matches[1]', 'top' );
// Movie Genres pagination
add_rewrite_rule( '^movies/movie-genres/([^/]+)/page/([0-9]+)?$',
'index.php?post_type=movie&genre=$matches[1]&paged=$matches[2]', 'top' );
// Game Genres
add_rewrite_rule( '^games/game-genres/([^/]+)/?$',
'index.php?taxonomy=genre&post_type=game&term=$matches[1]', 'top' );
// Game Genres pagination
add_rewrite_rule( '^games/game-genres/([^/]+)/page/([0-9]+)?$',
'index.php?post_type=game&genre=$matches[1]&paged=$matches[2]', 'top' );
}
add_action( 'init', 'wpse247013_rewrite_rules', 10, 0 );
Make sure to flush the rewrite rules by visiting Settings > Permalinks after adding this code to your plugin or theme. If you’re using a plugin, you can flush the rules programmatically using register_activation_hook.
Custom URLs
The rewrite rules added above will enable the following new URLs:
-
http://example.com/books/book-genres/{genre-term-slug}
(lists only books associated with the specified genre-term-slug )
-
http://example.com/movies/movie-genres/{genre-term-slug}
(lists only movies associated with the specified genre-term-slug )
-
http://example.com/games/game-genres/{genre-term-slug}
(lists only games associated with the specified genre-term-slug )