get_categories for custom post type with a specific custom taxonomy attached

Basically I have a custom post type of ‘products’ which has two taxonomies attached to it…the normal ‘category’ and a custom taxonomy called ‘brands’.

I have a page which is ‘brand’ specific. On this page I’d like to list all the ‘categories’ that have a ‘product’ in them with a term of the ‘brand’ whos page I’m on attached.

Read More

Eg. say I’m on the “Nike” page. I want it to list all categories that have a ‘product’ in them with the ‘brand’ of “Nike” attached to them.

My initial thoughts are to use get_categories but theres now way to define a specific taxonomy or ‘brand’?

$categories = get_categories('orderby=name&depth=1&hide_empty=0&child_of='.$cat);

Anyone done this before or knows a way to query the database directly to get the required results?

Any help is much appreicated, Thanks

Related posts

Leave a Reply

3 comments

  1. Hi @daveaspi:

    What you want to do is common but not well handled in WordPress core. There are probably ways to do it without custom SQL but I don’t think they would scale for a large number of posts. Below is a function I wrote called get_cross_referenced_terms() that will get what you want, complete with an example how to use it.

    This following code can be placed in the root of your WordPress site in a test.php file to
    see it work. You can then copy the function get_cross_referenced_terms() into your theme’s functions.php file or into a .php file of a plugin you might be working on:

    <?php 
    
      include('wp-load.php');
    
      $nike = get_term_by('slug','nike','brand'); // This here just to illustrate
    
      $terms = get_cross_referenced_terms(array(
        'post_type'        => 'product',
        'related_taxonomy' => 'brand',
        'term_id'          => $nike->term_id,
      ));
      foreach($terms as $term) {
        echo "<p>{$term->name}</p>";
      }
    
    function get_cross_referenced_terms($args) {
      global $wpdb;
      $args = wp_parse_args($args,array(
        'post_type'        => 'post',
        'taxonomy'         => 'category',
        'related_taxonomy' => 'post_tag',
        'term_id'          => 0,
      ));
      extract($args);
      $sql = <<<SQL
    SELECT DISTINCT
      {$wpdb->terms}.*,
      COUNT(*) AS post_count
    FROM
      {$wpdb->terms}
      INNER JOIN {$wpdb->term_taxonomy} ON {$wpdb->terms}.term_id={$wpdb->term_taxonomy}.term_id
      INNER JOIN {$wpdb->term_relationships} ON {$wpdb->term_taxonomy}.term_taxonomy_id={$wpdb->term_relationships}.term_taxonomy_id
      INNER JOIN {$wpdb->posts} ON {$wpdb->term_relationships}.object_id={$wpdb->posts}.ID
      INNER JOIN {$wpdb->term_relationships} related_relationship ON {$wpdb->posts}.ID=related_relationship.object_id
      INNER JOIN {$wpdb->term_taxonomy} related_term_taxonomy ON related_relationship.term_taxonomy_id=related_term_taxonomy.term_taxonomy_id
      INNER JOIN {$wpdb->terms} related_terms ON related_term_taxonomy.term_id=related_terms.term_id
    WHERE 1=1
      AND (related_term_taxonomy.taxonomy<>{$wpdb->term_taxonomy}.taxonomy OR related_terms.term_id<>{$wpdb->terms}.term_id)
      AND {$wpdb->posts}.post_type='%s'
      AND {$wpdb->term_taxonomy}.taxonomy='%s'
      AND related_term_taxonomy.taxonomy='%s'
      AND related_terms.term_id=%d
    GROUP BY
      {$wpdb->terms}.term_id
    SQL;
      $sql = $wpdb->prepare($sql,$post_type,$taxonomy,$related_taxonomy,$term_id);
      $terms = $wpdb->get_results($sql);
      return $terms;
    }
    
  2. If you want to list all the available categories for a custom post type, this snippet might help you.

    Just use the standard get_categories() function and pass the $args relating to the taxonomy you registered for your CPT. So, if you defined your taxonomy like this:

    register_taxonomy( 'the_taxonomy_named_in_your_CPT' );
    

    Then you’d show the taxonomy to front end users via:

    $args = array( 
        'taxonomy'     => 'the_taxonomy_named_in_your_CPT',
        'orderby'      => 'name',
        'show_count'   => 1,
        'pad_counts'   => 1, 
        'hierarchical' => 1,
        'echo'         => 0
    );
    
    $allthecats = get_categories( $args );
    echo ( '<pre>' );
    print_r( $allthecats );
    echo ( '</pre>' );
    

    You will see an object which will help you on your way.

  3. You can either code a custom sql query or you can query your post type for that “brand” and collect the categories and then display them, something like:

    //get all your post of that type fo that spesific brand
    $my_query = new WP_Query();
    $my_query->query(array(
        'post_type' => 'products',
        'posts_per_page' => -1,
        'tax_query' => array(
            array(
                'taxonomy' => 'brand',
                'field' => 'slug',
                'terms' => $wp_query->query_vars['brand']
            )
        )
        ));
    $my_cats = array(); 
    if ($my_query->have_posts()){
    //loop over all post and collect the categories in to an array
        while ($my_query->have_posts()){
            $my_query->the_post();
            foreach((get_the_category($post->ID)) as $category) {
                if (!in_array($category->cat_ID ,$my_cats)){
                    $my_cats[] = $category->cat_ID;
                }
            } 
        }
    }
    

    and here you have the list of all categories ID in an array $my_cats.
    which you can get all the info you need from