Custom Post Types and independent Categories – complex Taxonomy

Input data:

  1. There is a Custom Post Type, with Companies posts that relates
    to Company category;
  2. There is a Custom Post Type, with
    Products posts that tied to Items -> Item-type category;
  3. There is a Custom Post Type, with Articles posts that tied to
    Articles category;

Summarizing, structure looks like this:

Read More
+ Companies (cat)
   |- Company-1 (post)
   `- Company-2
+ Items (cat)
   `- Item-type-1 (cat)
   |   |- Product-1-1 (post)
   |   `- Product-1-2
   `- Item-type-2 (cat)
       |- Product-2-1 (post)
       `- Product-2-2
+ Articles (cat)
   |- Article-1 (post)
   `- Article-2

The Problem:

I’ll be appreciate for a way to implement the structure that can be accessed like this:

http://example.com/company-1/items/item-type-1/product-1 
http://examplecom/company-2/items/item-type-1/product-1 //(note that both company 1 and 2 can produce a similar product)
http://example.com/company-1/articles/article-1-1
http://example.com/company-2/articles/article-2-1

Both Products and Articles posts have got a custom fields that stores post-IDs of companies they’re tied to.

UPDATE:

I was thinking about developing it with custom taxonomies:

http://example.com/post-type-company/taxonomy-item/term-item-type/product

Can you advice more suitable way?

Related posts

1 comment

  1. In wordpress, the slug (post name) is unique per post type.

    So, an url like /company-1/items/item-type-1/product-1 and one like /company-2/items/item-type-1/product-1 where product-1 is the post name, cannot address to 2 different products.

    If you create 2 products with same title WordPress on saving will set an unique slug.

    Same thing is for articles.

    For this reason in a url like:

    http://example.com/company-1/items/item-type-1/product-1
    

    can simply be rewritten in

    http://example.com/index.php?post_type=products&name=product-1 
    

    and a url like:

    http://example.com/company-1/articles/article-1-1
    

    can simply be rewritten in

    http://example.com/index.php?post_type=articles&name=article-1-1
    

    So, as you can see, no matter for category.

    You need only 2 rewrite rules:

    add_action('init','my_rewrite_rules');
    
    function my_rewrite_rules() {
        add_rewrite_rule( '[^/]+/items/[^/]+/(.+)/?$' , 'index.php?post_type=products&name=$matches[1]' , 'top' );
        add_rewrite_rule( '[^/]+/articles/(.+)/?$' , 'index.php?post_type=articles&name=$matches[1]' , 'top' );
    }
    

    After that you have to flushing rewrite rules going Settings->Permalink section in your backend and saving changes.

    Now the urls work as you expect, if you manually write them on browser, but the problem is generate the right url using the_permalink function. You have to use the ‘post_link’ filter and generate the right url:

    add_filter('post_link', 'my_custom_permalink', 99, 3);
    
    function my_custom_permalink($permalink, $post, $leavename) {
      if ( $post->post_type == 'products' )
         return products_permalink($permalink, $post, $leavename);
      if ( $post->post_type == 'articles' )
         return articles_permalink($permalink, $post, $leavename);
      return $permalink;
    }
    
    function products_permalink($permalink, $post, $leavename) {
      if ( $post->post_type != 'products' ) return $permalink;
      $cats = get_the_category( $post->ID );
      $companies = get_term_by('slug', 'companies', 'category');
      $items= get_term_by('slug', 'items', 'category');
      if ( empty($cats) || empty($companies) || empty($items) ) return $permalink;
      $item = '';
      $company = '';
      while ( ! empty($cats) ) {
        if ( $item && $company )
          return home_url() . '/' . $company . '/items/' . $item . '/' . $post->name;
        $cat = array_pop($cats);
        if ( $cat->parent == $companies->term_id ) $company = $cat->slug;
        if ( $cat->parent == $items->term_id ) $item = $cat->slug;
      }
      return $permalink;
    }
    
    function articles_permalink($permalink, $post, $leavename) {
      if ( $post->post_type != 'articles' ) return $permalink;
      $cats = get_the_category( $post->ID );
      $companies = get_term_by('slug', 'companies', 'category');
      if ( empty($cats) || empty($companies) ) return $permalink;
      $company = '';
      while ( ! empty($cats) ) {
        if ( $company )
          return home_url() . '/' . $company . '/articles/' . $post->name;
        $cat = array_pop($cats);
        if ( $cat->parent == $companies->term_id ) $company = $cat->slug;
      }
      return $permalink;
    }
    

    Here I assume you are using only standard categories, where the category ‘Companies’ is the parent category for companies and ‘Items’ is the parent category for items.

    Also assumed cpt are named ‘products’ and ‘articles’ (note the plural).

    Ajust the functions if something is different in your configuration.

Comments are closed.