3

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

2 Answers 2

8

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

Single post type URLs

Taxonomy Term archive URLs

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:

7
  • WOW! I will test it in the next days! Thank you very much for this answer ;)
    – Cray
    Nov 28, 2016 at 13:30
  • You got it, keep me posted! Nov 28, 2016 at 19:49
  • works like a charm ;)
    – Cray
    Nov 30, 2016 at 14:34
  • one last question: is it ok to use only the term "genres" in the URL (without book-, movie- or game-)? I've tried it and it's working. But I'm not sure if maybe there are problems I don't see?! (For example: add_rewrite_rule( '^movies/genres/....)
    – Cray
    Nov 30, 2016 at 16:06
  • Yes, that should be fine. I tested this setup, and the the URLs under Basic URL Examples and Custom URLs in my answer still worked correctly. Nov 30, 2016 at 22:48
0

You can register taxonomy dynamically like this,

add_action('init',function(){

    $postType = array( 'books','movies','games' );

    foreach ( $postType as $k => $cpt ) {

        $tax_slug = strtolower( $cpt ) . '-genre';

        register_taxonomy(
            $tax_slug,
            strtolower( $cpt ),
            array(
                    'label' => 'Genre',
                    'rewrite' => array( 'slug' => $tax_slug ),
                    'hierarchical' => true,
                )
        );
    }
});
2
  • Thanks for your answer! But how could I use this as archive or link to an archive page?
    – Cray
    Nov 22, 2016 at 14:37
  • OK. I've tried your solution and added the code to my functions.php. Unfortunately it's not what I need. The code adds an extra taxonomy to my already existing one.
    – Cray
    Nov 22, 2016 at 15:31

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.