2
votes

I have created a custom post type 'Shop' with a custom taxonomy for Shop Categories

For my shop category archive pages I want the URL structure to be:

example.com/shop/tech/ (instead of example.com/shop/category/tech/)

And I want Shop posts to be example.com/shop/shop-post-title-example

I have tried the code below and saved permalinks but when I visit a Shop post it shows a 404 error.

Is it possible to remove the category base without errors?

// Custom Post Type : Shop  
function my_custom_post_shop() {
  $labels = array(
    'name'               => _x( 'Shop', 'post type general name' ),
    'singular_name'      => _x( 'Product', 'post type singular name' ),
    'add_new'            => _x( 'Add New', 'Product' ),
    'add_new_item'       => __( 'Add New' ),
    'edit_item'          => __( 'Edit' ),
    'new_item'           => __( 'New Product' ),
    'all_items'          => __( 'All Products' ),
    'view_item'          => __( 'View Product' ),
    'search_items'       => __( 'Search Products' ),
    'not_found'          => __( 'No projects found' ),
    'not_found_in_trash' => __( 'No projects found in the Trash' ), 
    'menu_name'          => 'Shop'
  );
  $args = array(
        'label'               => __( 'Shop' ),
        'labels'              => $labels,
        'supports'            => array( 'title', 'editor', 'excerpt', 'author', 'comments', 'revisions', 'custom-fields', 'thumbnail', ),
        'hierarchical'        => false,
        'public'              => true,
        'show_ui'             => true,
        'show_in_menu'        => true,
        'show_in_nav_menus'   => true,
        'show_in_admin_bar'   => true,
        'menu_position'       => 5,
        'can_export'          => true,
        'exclude_from_search' => false,
        'publicly_queryable'  => true,
        'capability_type'     => 'post',
        'rewrite' => array( 'slug' => 'shop' ),
        'has_archive' => 'shop',
  );
  register_post_type( 'shop', $args ); 
}
add_action( 'init', 'my_custom_post_shop' );

// Shop Categories
function my_taxonomies_shop() {
  $labels = array(
    'name'              => _x( 'Shop Categories', 'taxonomy general name' ),
    'singular_name'     => _x( 'Shop Category', 'taxonomy singular name' ),
    'search_items'      => __( 'Search Categories' ),
    'all_items'         => __( 'All Categories' ),
    'parent_item'       => __( 'Parent Category' ),
    'parent_item_colon' => __( 'Parent Category:' ),
    'edit_item'         => __( 'Edit Category' ), 
    'update_item'       => __( 'Update Category' ),
    'add_new_item'      => __( 'Add New Category' ),
    'new_item_name'     => __( 'New Category' ),
    'menu_name'         => __( 'Shop Categories' ),
  );
  $args = array(
    'labels' => $labels,
    'hierarchical' => true,
    'show_admin_column' => true,
    'rewrite' => array( 'slug' => 'shop'),
  );
  register_taxonomy( 'shop_category', 'shop', $args );
}
add_action( 'init', 'my_taxonomies_shop', 0 );
2

2 Answers

1
votes

You can remove the category base in custom taxonomy URLs with:

$args = array(

    'rewrite' => array( 'slug' => '/', 'with_front' => false),

    /* ...(other args)... */
);
register_taxonomy( 'shop_category', 'shop', $args );

And re-save Permalinks settings.

However, this will make your (basic post type) posts go 404, if you have permalinks set to Post name. It seems you cannot have both custom taxonomy and posts reside in the root. Therefore you would go to Permalinks settings and set Custom structure , e.g. /blog/%postname%/.

A side effect is that your CPTs would have this "front", too, e.g. blog/yourcustomtype. You can get rid of this with 'with_front' => false in your product type registration:

register_post_type( 'yourcustomtype',  array(
           'rewrite' => array(
                'slug' => 'yourcustomurl',
                'with_front' => false
            ),
            /* ... */
));

Found here.

0
votes

As far as I know, in order to display custom post type and/or its category page, you would need to create template files (corresponding PHP files) first. Template files would pull your posts and display them.

For example, to display your categories "shop_category" you could create a file called "taxonomy-shop_category.php".
If you like to create a template specifically for "tech" Shop Category, then you can create a file called "taxonomy-shop_category_tech.php".
There is a hierarchy of templates: https://wphierarchy.com/ Also more about templates: https://developer.wordpress.org/themes/template-files-section/taxonomy-templates/
Nice article about custom post types taxonomies: https://code.tutsplus.com/tutorials/taxonomy-archives-list-posts-by-post-type--cms-20340

Template files should be placed in your WordPress theme folder (or child theme folder)
!important. Don't forget to update your permalinks. Go to /wp-admin/options-permalink.php and click "Save Changes".

Here is an example of a simple template file:

<?php
if ( ! defined( 'ABSPATH' ) ) { exit; }
?>
 
<?php get_header(); 
$term = get_queried_object();

$args = array(
    'post_type' => 'shop',
    'shop-category' => $term->slug
);
$query = new WP_Query( $args );

?>
 <header class="archive-header">
    <h1 class="archive-title">
        <?php echo $term->name; ?>
    </h1>
</header>
        <div id="content">
                 <?php
                 if ($query->have_posts()) {
                         
                    echo'<h2>Your shop category name ' . $term->name . '</h2>';
                     
                    echo '<ul>';
                     
                        while ( $query->have_posts() ) : $query->the_post(); ?>
                 
                        <li id="post-<?php the_ID(); ?>">
                            <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
                        </li>
                         
                        <?php endwhile;
                         
                        echo '</ul>';
                         
                } 
                     
                wp_reset_postdata();
                ?>             
             
        </div><!-- #content -->

<?php
get_footer();