get_categories for Custom Post Type

I have a Custom Post Type, ‘ioni_codex’
I am using built-in WordPress category as taxonomy

I want to list all categories used by ‘ioni_codex’.

Read More

I assume that this code will do the trick:

$myargs = array (
    'type' => 'ioni_codex'
); 
$categories = get_categories( $myargs );

However instead I see the list of all categories not the categories assigned to by ‘ioni_codex’.

What Am I doing wrong?

Related posts

Leave a Reply

4 comments

  1. Instead of type you have to set post_type , by default get_categories try to hide empty categories , if you want display it all add hide_empty property set to false

     get_categories(array(
        'post_type' => 'ioni_codex',
        'hide_empty' => false,
       ) );
    
    
  2. I have an answer at a sister project:
    Bainternet♦ has re-written get_terms() function to provide for the post_type

    Please refer to his solution here or just copy and past from below:

    /* get terms limited to post type 
     @ $taxonomies - (string|array) (required) The taxonomies to retrieve terms from. 
     @ $args  -  (string|array) all Possible Arguments of get_terms http://codex.wordpress.org/Function_Reference/get_terms
     @ $post_type - (string|array) of post types to limit the terms to
     @ $fields - (string) What to return (default all) accepts ID,name,all,get_terms. 
     if you want to use get_terms arguments then $fields must be set to 'get_terms'
    */
    function get_terms_by_post_type($taxonomies,$args,$post_type,$fields = 'all'){
        $args = array(
            'post_type' => (array)$post_type,
            'posts_per_page' => -1
        );
        $the_query = new WP_Query( $args );
        $terms = array();
        while ($the_query->have_posts()){
            $the_query->the_post();
            $curent_terms = wp_get_object_terms( $post->ID, $taxonomy);
            foreach ($curent_terms as $t){
              //avoid duplicates
                if (!in_array($t,$terms)){
                    $terms[] = $c;
                }
            }
        }
        wp_reset_query();
        //return array of term objects
        if ($fields == "all")
            return $terms;
        //return array of term ID's
        if ($fields == "ID"){
            foreach ($terms as $t){
                $re[] = $t->term_id;
            }
            return $re;
        }
        //return array of term names
        if ($fields == "name"){
            foreach ($terms as $t){
                $re[] = $t->name;
            }
            return $re;
        }
        // get terms with get_terms arguments
        if ($fields == "get_terms"){
            $terms2 = get_terms( $taxonomies, $args );
            foreach ($terms as $t){
                if (in_array($t,$terms2)){
                    $re[] = $t;
                }
            }
            return $re;
        }
    }
    
  3. While quick reading @ioni’s answer; it looks like it would give you a proper result it will most likely be pretty slow as it goes through every post and then looks for all terms that belong to each post individually. This will easily result in thousands of SQL queries.

    My recommendation is to use a single query to get the IDs of all terms that belong to a post type. Then use those ids to filter get_terms().

    MySQL query:

    SELECT
        wp_term_taxonomy.term_id
    FROM
        wp_term_relationships
    LEFT JOIN wp_posts ON wp_term_relationships.object_id = wp_posts.ID
    LEFT JOIN wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
    WHERE
        wp_term_taxonomy.taxonomy = 'category'
    AND wp_posts.post_type = 'ioni_codex'
    GROUP BY
        term_id
    

    PHP function:

    <?php
    
    function ioni_get_terms_by_post_type( $taxonomy = 'category', $post_type = 'post', $args = array() ) {
        global $wpdb;
    
        $sql = $wpdb->prepare(
            "
                SELECT
                    {$wpdb->prefix}term_taxonomy.term_id
                FROM
                    {$wpdb->prefix}term_relationships
                LEFT JOIN {$wpdb->prefix}posts ON {$wpdb->prefix}term_relationships.object_id = {$wpdb->prefix}posts.ID
                LEFT JOIN {$wpdb->prefix}term_taxonomy ON {$wpdb->prefix}term_relationships.term_taxonomy_id = {$wpdb->prefix}term_taxonomy.term_taxonomy_id
                WHERE
                    {$wpdb->prefix}term_taxonomy.taxonomy = '%s'
                AND {$wpdb->prefix}posts.post_type = '%s'
                GROUP BY
                    term_id
            ",
            $taxonomy,
            $post_type,
        );
        $term_ids = $wpdb->get_col( $sql );
        
        if ( empty( $term_ids ) ) {
            return array();
        }
    
        // custom code to allow for exclude to work
        if ( ! empty( $args['exclude'] ) ) {
            // allow exclude to be either a string or array
            $exclude = is_string(  $args['exclude'] ) ? (array) $args['exclude'] : $args['exclude'];
            
            // filter $term_ids with array from $args['exclude']
            $term_ids = array_filter( $term_ids, function( $term_id ) use ( $exclude ) {
                return ! in_array( $term_id, $exclude );
            } );
        }
    
        $args = wp_parse_args(
            $args,
            array(
                'taxonomy' => $taxonomy,
                'include' => $term_ids,
            ),
        );
    
        return get_terms( $args );
    }
    

    Usage:

    <?php
    
    $categories = ioni_get_terms_by_post_type( 'category', 'ioni_codex' );