Custom Rewrite Rules

On this project we had a custom post type called “resource” and a taxonomy called “resource_type”. We wanted the following URLs:

  • /resource – CPT Archive for resource
  • /resource/ebooks – Tax archive for “ebook” term in the resource_type taxonomy
  • /resource/ebooks/sample-ebook – Single post in resource CPT

Some things to note below:

  • Line 71, the resource_type taxonomy has its rewrite slug set to resource.
  • Line 197, the resource CPT has its rewrite slug set to resource/%resource_type%.
  • Lines 210-212, registering the different rewrite rules.
  • Lines 220-230, filtering the post type link (singular) to change %resource_type% to an actual taxonomy term slug. Not shown is the ea_first_term() function that gets the terms and selects the first if multiple terms are attached to post.
  • Lines 236-240, filters the post type archive link, removing the %resource_type% so that it is just /resource.
<?php
/**
* Core Functionality Plugin
*
* @package CoreFunctionality
* @since 1.0.0
* @copyright Copyright (c) 2017, Bill Erickson
* @license GPL-2.0+
*/
/**
* Resources
*
* This file registers the resource custom post type
* and setups the various functions and items it uses.
*
* @since 1.2.0
*/
class EA_Resource {
/**
* Initialize all the things
*
* @since 1.2.0
*/
function __construct() {
// Actions
add_action( 'init', array( $this, 'tax_resource_type' ) );
add_action( 'init', array( $this, 'tax_resource_topic' ) );
add_action( 'init', array( $this, 'tax_library_tag' ) );
add_action( 'init', array( $this, 'register_cpt' ) );
add_action( 'init', array( $this, 'rewrite_rules' ) );
add_filter( 'post_type_link', array( $this, 'post_type_link' ), 10, 2 );
add_filter( 'post_type_archive_link', array( $this, 'post_type_archive_link' ), 10, 2 );
add_action( 'pre_get_posts', array( $this, 'archive_query' ) );
}
/**
* Register the Resource Type taxonomy
*
* @since 1.2.0
*/
function tax_resource_type() {
$labels = array(
'name' => 'Resource Types',
'singular_name' => 'Type',
'search_items' => 'Search Types',
'popular_items' => 'Popular Types',
'all_items' => 'All Types',
'parent_item' => 'Parent Type',
'parent_item_colon' => 'Parent Type:',
'edit_item' => 'Edit Type',
'update_item' => 'Update Type',
'add_new_item' => 'Add New Type',
'new_item_name' => 'New Type',
'separate_items_with_commas' => 'Separate Types with commas',
'add_or_remove_items' => 'Add or remove Types',
'choose_from_most_used' => 'Choose from most used Types',
'menu_name' => 'Types',
);
$args = array(
'labels' => $labels,
'public' => true,
'show_in_nav_menus' => true,
'show_ui' => true,
'show_tagcloud' => false,
'hierarchical' => true,
'rewrite' => array( 'slug' => 'resource', 'with_front' => false ),
'query_var' => true,
'show_admin_column' => true,
// 'meta_box_cb' => false,
);
register_taxonomy( 'resource_type', array( 'resource' ), $args );
}
/**
* Register the Resource Topic
*
* @since 1.2.0
*/
function tax_resource_topic() {
$labels = array(
'name' => 'Resource Topics',
'singular_name' => 'Topic',
'search_items' => 'Search Topics',
'popular_items' => 'Popular Topics',
'all_items' => 'All Topics',
'parent_item' => 'Parent Topic',
'parent_item_colon' => 'Parent Topic:',
'edit_item' => 'Edit Topic',
'update_item' => 'Update Topic',
'add_new_item' => 'Add New Topic',
'new_item_name' => 'New Topic',
'separate_items_with_commas' => 'Separate Topics with commas',
'add_or_remove_items' => 'Add or remove Topics',
'choose_from_most_used' => 'Choose from most used Topics',
'menu_name' => 'Topics',
);
$args = array(
'labels' => $labels,
'public' => true,
'show_in_nav_menus' => true,
'show_ui' => true,
'show_tagcloud' => false,
'hierarchical' => true,
'rewrite' => array( 'slug' => 'resource-topic', 'with_front' => false ),
'query_var' => true,
'show_admin_column' => true,
// 'meta_box_cb' => false,
);
register_taxonomy( 'resource_topic', array( 'resource' ), $args );
}
/**
* Register the Library Tag taxonomy
*
* @since 1.2.0
*/
function tax_library_tag() {
$labels = array(
'name' => 'Library Tags',
'singular_name' => 'Library Tag',
'search_items' => 'Search Tags',
'popular_items' => 'Popular Tags',
'all_items' => 'All Tags',
'parent_item' => 'Parent Tag',
'parent_item_colon' => 'Parent Tag:',
'edit_item' => 'Edit Tag',
'update_item' => 'Update Tag',
'add_new_item' => 'Add New Tag',
'new_item_name' => 'New Tag',
'separate_items_with_commas' => 'Separate Tags with commas',
'add_or_remove_items' => 'Add or remove Tags',
'choose_from_most_used' => 'Choose from most used Tags',
'menu_name' => 'Tags',
);
$args = array(
'labels' => $labels,
'public' => true,
'show_in_nav_menus' => true,
'show_ui' => true,
'show_tagcloud' => false,
'hierarchical' => false,
'rewrite' => array( 'slug' => 'library-tag', 'with_front' => false ),
'query_var' => true,
'show_admin_column' => true,
// 'meta_box_cb' => false,
);
register_taxonomy( 'library_tag', array( 'resource', 'learning' ), $args );
}
/**
* Register the custom post type
*
* @since 1.2.0
*/
function register_cpt() {
$labels = array(
'name' => 'Resources',
'singular_name' => 'Resource',
'add_new' => 'Add New',
'add_new_item' => 'Add New Resource',
'edit_item' => 'Edit Resource',
'new_item' => 'New Resource',
'view_item' => 'View Resource',
'search_items' => 'Search Resources',
'not_found' => 'No Resources found',
'not_found_in_trash' => 'No Resources found in Trash',
'parent_item_colon' => 'Parent Resource:',
'menu_name' => 'Resources',
);
$args = array(
'labels' => $labels,
'hierarchical' => false,
'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'author', 'comments', 'discussion' ),
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_nav_menus' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite' => array( 'slug' => 'resource/%resource_type%', 'with_front' => false ),
'menu_icon' => 'dashicons-format-aside', // https://developer.wordpress.org/resource/dashicons/
);
register_post_type( 'resource', $args );
}
/**
* Rewrite Rules
*
*/
function rewrite_rules() {
add_rewrite_rule( 'resource/page/?([0-9]{1,})/?$', 'index.php?post_type=resource&paged=$matches[1]', 'top' );
add_rewrite_rule( 'resource/(.+)/page/?([0-9]{1,})/?$', 'index.php?resource_type=$matches[2]&paged=$matches[3]', 'top' );
add_rewrite_rule( 'resource/?$', 'index.php?post_type=resource', 'top' );
}
/**
* Post Type Link
*
*/
function post_type_link( $link, $post ) {
if( 'resource' != $post->post_type )
return $link;
$term = ea_first_term( 'resource_type', false, $post->ID );
$slug = !empty( $term ) && ! is_wp_error( $term ) ? $term->slug : 'uncategorized';
$link = str_replace( '%resource_type%', $slug, $link );
return $link;
}
/**
* Post Type Archive Link
*
*/
function post_type_archive_link( $link, $post_type ) {
if( 'resource' == $post_type )
$link = str_replace( '/%resource_type%', '', $link );
return $link;
}
/**
* Archive Query
*
*/
function archive_query( $query ) {
if( $query->is_main_query() && ! is_admin() && ea_is_resource_library() ) {
$query->set( 'posts_per_page', 20 );
$tax_query = ea_get_tax_query();
if( !empty( $tax_query ) )
$query->set( 'tax_query', $tax_query );
}
}
}
new EA_Resource();
/**
* Is Resource Library? conditional
*
*/
function ea_is_resource_library() {
return is_post_type_archive( 'resource' ) || is_tax( array( 'resource_type', 'resource_topic', 'library_tag' ) );
}
view raw cpt-resource.php hosted with ❤ by GitHub

Bill Erickson

Bill Erickson is a freelance WordPress developer and a contributing developer to the Genesis framework. For the past 14 years he has worked with attorneys, publishers, corporations, and non-profits, building custom websites tailored to their needs and goals.

Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk