2

I've been working with Custom Post Types and Custom Taxonomies for ages but one thing I can never get right are the rewrites when applying a shared taxonomy to multiple CPTs.

For instance, I have CPTs for 'Events' and 'Courses'. Each has individual taxonomies and also one shared taxonomy.

The individual taxonomies work fine:

  • Events with a specific topic: /events/topic/{term}/
  • Courses of a specific type: /courses/type/{term}/

However, I have a shared taxonomy called 'Accessibility Criteria'. With the custom taxonomy defined as it is below, I want (and would expect) to be able to filter each CPT by the shared taxonomy at different URLs:

  • Events with specific accessibility criteria: /events/accessibility/{term}/
  • Courses with specific accessibility criteria: /courses/accessibility/{term}/

But whenever I try and use /events/accessibility/{term}/ it gets rewritten as /accessibility/{term}/. Surprisingly (to me), the context is actually retained correctly e.g. if I trigger the taxonomy from the Events archive then only Event CPTs are shown, so the end-user experience still works fine. However, it doesn't sit comfortably with me as I feel it should work differently (as well as potentially better SEO etc).

I have defined the custom taxonomies before defining the CPTs as I have read that affects the ability of a CPT to use the taxonomy rewrite.

Any help much appreciated.

$labels = array(
  "name" => __('Accessibility Criteria', ''),
  "singular_name" => __('Accessibility Criteria', ''),
  "add_new_item" => __('Add Accessibility Criteria', ''),
  "new_item_name" => __('Add Accessibility Criteria', ''),
  "edit_item" => __('Edit Accessibility Criteria', ''),
  "view_item" => __('View Accessibility Criteria', ''),
  "update_item" => __('Update Accessibility Criteria', ''),
  "parent_item" => __('Parent Criteria', '')
);
$args = array(
  "label" => __('Accessibility Criteria', ''),
  "labels" => $labels,
  "public" => true,
  "hierarchical" => true,
  "label" => "Accessibility Criteria",
  "show_ui" => true,
  "show_in_menu" => true,
  "show_in_nav_menus" => false,
  "capabilities" => array(
    'manage_terms' => 'manage_accessibility_criteria',
    'edit_terms'   => 'edit_accessibility_criteria',
    'delete_terms' => 'delete_accessibility_criteria',
    'assign_terms' => 'assign_accessibility_criteria'
  ),
  "query_var" => 'accessibility_criteria',
  "rewrite" => array('slug' => 'accessibility', 'with_front' => true),
  "show_admin_column" => true,
  "show_in_rest" => false,
  "rest_base" => "",
  "show_in_quick_edit" => true,
);
register_taxonomy("accessibility_criteria", array("event", "course"), $args);
  • 2
    Really? No-one? Come on... everyone loves CPT questions. Someone knows how to do this and can put me straight surely. :-) – onebc Jan 29 '18 at 17:31
  • I have the same problem and have not found a solution... not much of a comment help but will upvote your question. Maybe you can put a bounty on it or I will. – Enkode May 15 '18 at 5:13
0

I think you need to add a rewrite rule as the "normal" rewrite rules don't support your wanted permalink structure. For your use case, you can try it like this:

First: remove the "rewrite" argument from your register_taxonomy arguments (not sure if you definitely need to do this, but it works on my site)

Second: Add the rewrite rule like this in your functions.php

add_action( 'init', 'wpse13483_init' );
function wpse292188_init(){   
    add_rewrite_rule('(events|courses)/accessibility/([^/]+)(/page/?([0-9]{1,}))?/?$','index.php?post_type=$matches[1]&taxonomy=accessibility&term=$matches[2]&paged=$matches[3]','top');
}

Don't forget to save permalinks after uploading!

Happy Coding!

  • Thanks, I was able to get the rewrite to work but that is only half my battle. I need some solution that allows me to do the rewrite AND allows me to load a custom template for that taxonomy. – Enkode May 15 '18 at 23:44
  • Erm.... Where in the question do you state that you need to load a custom template?? Dont get me wrong, i will edit the answer when i get to Work, but next time please ask your full question... – kuchenundkakao May 16 '18 at 4:00
  • It is in the bounty text.. I think I might have a solution... maybe I will try and use the pattern to load a different section of the page and hide the current taxonomy. Not the cleanest but it will work. – Enkode May 16 '18 at 6:19
0

You have to add these permalinks by your own. I do not see any code in WordPress which is creating $post_type/$taxonomy/$term permalinks. I do not see such a rules also in my rewrite rule array after creating custom taxonomy assigned only to one custom post type. Behavior of your application might be caused by some plugin. Below you will find code which will add custom permalinks for $post_type/$taxonomy/$term structure and load custom template when such a permalink is visited.

<?php
/**
 * Register event post type
 *
 * Method is used by init hook
 */
function wpse_292188_register_event_post_type() {

    $labels = array(
        'name' => __( 'Events' ),
        'singular_name' => __( 'Event' ),
        'add_new' => __( 'Add new' ),
        'add_new_item' => __( 'Add new' ),
        'edit_item' => __( 'Edit' ),
        'new_item' => __( 'New' ),
        'view_item' => __( 'View' ),
        'search_items' => __( 'Search' ),
        'not_found' => __( 'Not found' ),
        'not_found_in_trash' => __( 'Not found Events in trash' ),
        'parent_item_colon' => __( 'Parent' ),
        'menu_name' => __( 'Events' ),

    );

    $args = array(
        'labels' => $labels,
        'hierarchical' => false,
        'supports' => array( 'title', 'page-attributes' ),
        'taxonomies' => array(),
        'public' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'show_in_nav_menus' => false,
        'publicly_queryable' => true,
        'exclude_from_search' => false,
        'has_archive' => true,
        'query_var' => true,
        'can_export' => true,
        'rewrite' => array('slug' => 'event'),
        'capability_type' => 'post',
    );

    register_post_type( 'event', $args );
}

add_action( 'init', 'wpse_292188_register_event_post_type' );

/**
 * Register course post type
 *
 * Method is used by init hook
 */
function wpse_292188_register_course_post_type() {

    $labels = array(
        'name' => __( 'Courses' ),
        'singular_name' => __( 'Course' ),
        'add_new' => __( 'Add new' ),
        'add_new_item' => __( 'Add new' ),
        'edit_item' => __( 'Edit' ),
        'new_item' => __( 'New' ),
        'view_item' => __( 'View' ),
        'search_items' => __( 'Search' ),
        'not_found' => __( 'Not found' ),
        'not_found_in_trash' => __( 'Not found Courses in trash' ),
        'parent_item_colon' => __( 'Parent' ),
        'menu_name' => __( 'Courses' ),

    );

    $args = array(
        'labels' => $labels,
        'hierarchical' => false,
        'supports' => array( 'title', 'page-attributes' ),
        'taxonomies' => array(),
        'public' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'show_in_nav_menus' => false,
        'publicly_queryable' => true,
        'exclude_from_search' => false,
        'has_archive' => true,
        'query_var' => true,
        'can_export' => true,
        'rewrite' => array('slug' => 'course'),
        'capability_type' => 'post',
    );

    register_post_type( 'course', $args );
}

add_action( 'init', 'wpse_292188_register_course_post_type' );


/**
 * Register accessibility_criteria taxonomy
 *
 * Method is used by init hook
 */
function wpse_292188_register_accessibility_criteria_taxonomy() {

    $labels = array(
        'name'              => __( 'Accessibility Criteria', 'textdomain' ),
        'singular_name'     => __( 'Accessibility Criteria', 'textdomain' ),
        'search_items'      => __( 'Search Accessibility Criteria', 'textdomain' ),
        'all_items'         => __( 'All Accessibility Criteria', 'textdomain' ),
        'parent_item'       => __( 'Parent Accessibility Criteria', 'textdomain' ),
        'parent_item_colon' => __( 'Parent Accessibility Criteria:', 'textdomain' ),
        'edit_item'         => __( 'Edit Accessibility Criteria', 'textdomain' ),
        'update_item'       => __( 'Update Accessibility Criteria', 'textdomain' ),
        'add_new_item'      => __( 'Add New Accessibility Criteria', 'textdomain' ),
        'new_item_name'     => __( 'New Accessibility Criteria Name', 'textdomain' ),
        'menu_name'         => __( 'Accessibility Criteria', 'textdomain' ),
    );

    $args = array(
        'hierarchical'      => true,
        'labels'            => $labels,
        'show_ui'           => true,
        'show_admin_column' => true,
        'query_var'         => true,
        'rewrite'           => array( 'slug' => 'accessibility' ),
    );

    register_taxonomy( 'accessibility_criteria', array( 'event', 'course' ), $args );
}

add_action( 'init', 'wpse_292188_register_accessibility_criteria_taxonomy' );

/**
 * Add rewrite rules for common taxonomy
 *
 * @return void
 */
function wpse_292188_add_taxonomy_and_post_type_rewrite_rule() {

    /**
     * This rewrite rule will match sample following link
     *
     * /event/accessibility/criteria-1
     * /event/accessibility/criteria-1/page/2
     *
     * /course/accessibility/criteria-1
     * /course/accessibility/criteria-1/page/2
     *
     * and "redirect" it to index.php with such a arguments
     *
     * index.php?post_type=event&accessibility_criteria=criteria-1
     * index.php?post_type=event&accessibility_criteria=criteria-1&paged=2
     *
     * index.php?post_type=course&accessibility_criteria=criteria-1
     * index.php?post_type=course&accessibility_criteria=criteria-1&paged=2
     */
    add_rewrite_rule( 'event/accessibility/([^/]+)/?', 'index.php?post_type=event&accessibility_criteria=$matches[1]', 'top' );
    add_rewrite_rule( 'event/accessibility/([^/]+)/page/?([0-9]{1,})/?', 'index.php?pots_type=eventaccessibility_criteria=$matches[1]&paged=$matches[2]', 'top' );

    add_rewrite_rule( 'course/accessibility/([^/]+)/?', 'index.php?post_type=course&accessibility_criteria=$matches[1]', 'top' );
    add_rewrite_rule( 'course/accessibility/([^/]+)/page/?([0-9]{1,})/?', 'index.php?pots_type=courseaccessibility_criteria=$matches[1]&paged=$matches[2]', 'top' );

}

add_action( 'init', 'wpse_292188_add_taxonomy_and_post_type_rewrite_rule' );


/**
 * Register activation hooks. Only works in plugin file.
 */
register_activation_hook( __FILE__ , 'wpse_292188_activate' );
register_deactivation_hook( __FILE__ , 'wpse_292188_deactivate' );

/**
 * Activation function
 */
function wpse_292188_activate() {

    wpse_292188_add_taxonomy_and_post_type_rewrite_rule();
    flush_rewrite_rules();
}
/**
 * Deactivation function
 */
function wpse_292188_deactivate() {

    flush_rewrite_rules();
}

/**
 * Load proper template for taxonomy and post type rewrite rule
 *
 * @return string
 *
 * @throws \Exception When template do not exist.
 */
function wpse_292188_load_proper_template_for_taxonomy_and_post_type_rewrite_rule( $template ) {

    $post_type              = get_query_var('post_type');
    $accessibility_criteria = get_query_var('accessibility_criteria');

    /**
     * Check if current page has post type and accessibility_criteria custom
     * query var. If yest load our template.
     */
    if( $post_type && !empty( $post_type ) && $accessibility_criteria && !empty( $accessibility_criteria ) ) {

        /**
         * Locate our custom template. You can use $post_type and/or
         * $accessibility_criteria variables to create custom template.
         */
        $template = locate_template( array( 'taxonomy.php' ) );
    }

    if( $template == '' ) {
        throw new \Exception('No template found');
    }

    return $template;
}

add_filter( 'template_include', 'wpse_292188_load_proper_template_for_taxonomy_and_post_type_rewrite_rule' );

I'm using register_activation_hook and register_deactivation_hookso please put this code in your custom plugin.

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.