I have a custom post type in WordPress called Resources and a custom taxonomy called Resource Type. I want the URLs to be:
CPT: site-url/custom-tax/post-title
Taxonomy Archive: site-url/resources/custom-tax/
Archive: site-url/resources
The code below works to get what I want but it 404s the other archive pages - blog, author etc. I've only included the code that is not working. I have pinpointed it to the post type slug %resource-type% that breaks the other archives. How do I get the other archive pages working?
/* ## Resources ## */
function register_resource_post_type() {
$args = array(
'rewrite' => array(
'slug' => '%resource-type%',
'with_front' => false
),
);
register_post_type('resource', $args);
}
add_action('init', 'register_resource_post_type');
/* ## Resource Types ## */
function register_resource_type_taxonomy() {
$args = array(
'rewrite' => array(
'slug' => 'resources',
'with_front' => false,
),
);
register_taxonomy('resource-type', array('resource'), $args);
}
add_action('init', 'register_resource_type_taxonomy');
/* # Permalink Rewrite # */
function wpd_taxonomy_pagination_rewrites(){
add_rewrite_rule(
'resource-type/([^/]+)/page/([0-9]+)/?$',
'index.php?resource-type=$matches[1]&paged=$matches[2]',
'top'
);
}
add_action( 'init', 'wpd_taxonomy_pagination_rewrites' );
function wpd_post_link( $post_link, $id = 0 ){
$post = get_post($id);
if ( is_object( $post ) && $post->post_type == 'resource' ){
$terms = wp_get_object_terms( $post->ID, 'resource-type' );
if( $terms ){
foreach( $terms as $term ){
if( 0 == $term->parent ){
return str_replace( '%resource-type%' , $term->slug , $post_link );
}
}
} else {
return str_replace( '%resource-type%' , 'uncategorized', $post_link );
}
}
return $post_link;
}
add_filter( 'post_type_link', 'wpd_post_link', 1, 3 );
The issue is coming because %resource-type% as the post type slug is conflicting with other archives. Wordpress is not able to put correct query for other archives. To solve this you can manually adjust the rewrite rules while ensuring that other WordPress archives remain functional. The following code correctly rewrites only the required URLs while keeping blog, author, and other archives working.
function register_resource_post_type() {
$args = array(
'public' => true,
'has_archive' => 'resources', // Ensures archive works
'rewrite' => array(
'slug' => '%resource-type%', // This removes 'resources/' from post URLs
'with_front' => false,
),
'supports' => array('title', 'editor', 'thumbnail'),
);
register_post_type('resource', $args);
}
add_action('init', 'register_resource_post_type');
/* ## Register Resource Type Taxonomy ## */
function register_resource_type_taxonomy() {
$args = array(
'hierarchical' => true,
'public' => true,
'rewrite' => array(
'slug' => 'resources', // Keeps 'resources/' in taxonomy archive URLs
'with_front' => false,
),
);
register_taxonomy('resource-type', array('resource'), $args);
}
add_action('init', 'register_resource_type_taxonomy');
/* ## Custom Post Permalink ## */
function wpd_post_link($post_link, $post) {
if ($post->post_type !== 'resource') {
return $post_link;
}
$terms = wp_get_object_terms($post->ID, 'resource-type');
if ($terms && !is_wp_error($terms)) {
$term_slug = $terms[0]->slug;
} else {
$term_slug = 'uncategorized';
}
return home_url('/' . $term_slug . '/' . $post->post_name . '/');
}
add_filter('post_type_link', 'wpd_post_link', 10, 2);
/* ## Custom Rewrite Rules ## */
function custom_rewrite_rules() {
$resource_types = get_terms(array(
'taxonomy' => 'resource-type',
'hide_empty' => false,
));
if ($resource_types && !is_wp_error($resource_types)) {
foreach ($resource_types as $term) {
// Rule for individual posts: site-url/custom-tax/post-name
add_rewrite_rule(
$term->slug . '/([^/]+)/?$',
'index.php?post_type=resource&name=$matches[1]',
'top'
);
}
}
// Taxonomy archive: site-url/resources/custom-tax/
add_rewrite_rule(
'resources/([^/]+)/?$',
'index.php?resource-type=$matches[1]',
'top'
);
// General archive: site-url/resources
add_rewrite_rule(
'resources/?$',
'index.php?post_type=resource',
'top'
);
}
add_action('init', 'custom_rewrite_rules', 10, 0);
/* ## Flush Rewrite Rules on Activation ## */
function flush_rewrite_rules_on_activation() {
register_resource_post_type();
register_resource_type_taxonomy();
flush_rewrite_rules();
}
register_activation_hook(__FILE__, 'flush_rewrite_rules_on_activation');