Get direct children of custom taxonomy

You have two issues here, one is a performance issue, the other is big issue that should return a pile of errors if you enable debug

The performance issue here is your first instance where you are getting the terms. It seems that your goal here is to get only top level terms, yet you get all. I would just add 'parent' => 0 to the arguments to get only top level terms. You can then drop the condition where you check if ( $term->parent == 0 ) because all terms will be top level terms which will all have 0 as term parent, so this condition will always return true

Your big issue is with this code, and I don’t understand your logic here

    $uchildren =get_terms( $taxonomy, array('hide_empty' => 0, 'parent' => $term->term_id ));

    $children = array();
    foreach ($uchildren as $child) {
        $cterm = get_term_by( 'id', $child, $taxonomy );
        // If include array set, exclude unless in array.
        if ( is_array( $include ) && ! in_array( $cterm->slug, $include ) ) continue;
        $children[$cterm->name] = $cterm;
    }
    ksort($children);

You are correct in getting your direct term children, so your declaration of $uchildren is fine. From there everything goes haywire

  • Why are you using get_term_by() here. $child already holds the term properties as you have used get_terms() to retrieve the terms.

  • You are not just using get_term_by() wrongly here, but your arguments are invalid, and you are passing a complete object to it as well. You should consult the codex for proper use of this function. All in all, that section should be removed from your code

That section should look something like this

    $uchildren =get_terms( $taxonomy, array('hide_empty' => 0, 'parent' => $term->term_id ));

    $children = array();
    foreach ($uchildren as $child) {
        if ( is_array( $include ) && ! in_array( $child->slug, $include ) ) continue;
        $children[$child->name] = $child;
    }
    ksort($children);

EDIT

Here is a full working code with a couple of bugs fixed. Please see my comments in code for the updates

function my_dropdown_categories( $taxonomy, $current_selected = '', $include = null ) 
{
    /*
     * Declare your variable first. Without this, your code has a bug if no terms are found
     */
    $list_of_terms="";

    /**
    * Get all parent terms. Note we use 'parent' => 0 to only get top level terms
    *
    * @see get_terms
    * @link http://codex.wordpress.org/Function_Reference/get_terms
    */
    $terms = get_terms( $taxonomy, array( 'orderby' => 'name', 'parent' => 0 ) );

    /*
    * Use curlies here to enclose your statement. Also, check whether or not you have terms
    */
    if ( $terms && ! is_wp_error( $terms ) ) {

        /*
        * Moved this section inside your if statement. We don't want to display anything on empty terms
        */
        $list_of_terms .= '<select id="location" class="selectboxSingle" name="location">';

        foreach ( $terms as $term ) {

            // If include array set, exclude unless in array.
            if ( is_array( $include ) && ! in_array( $term->slug, $include ) ) continue;

            $select = ($current_selected == $term->slug) ? "selected" : ""; // Note: ==

            /*
             * Use the parent term term id as parent to get direct children of the term
             * Use child_of if you need to get all descendants of a term
             */
            $uchildren = get_terms( $taxonomy, array('hide_empty' => 0, 'parent' => $term->term_id ));

            $children = array();
            foreach ($uchildren as $child) {
                // If include array set, exclude unless in array.
                if ( is_array( $include ) && ! in_array( $child->slug, $include ) ) continue;
                $children[$child->name] = $child;
            }
            ksort($children);

            // PARENT TERM      
            if ($term->count > 0) {
                $list_of_terms .= '<option class ="group-result" value="'.$term->slug.'" '.$select.'>' . $term->name .' </option>';
            } else {
                $list_of_terms .= '<option value="'.$term->slug.'" '.$select.'>'. $term->name .' </option>';
            };

            // now the CHILDREN.
            foreach($children as $child) {
                $select = ($current_selected == $child->slug) ? "selected" : ""; // Note: child, not cterm
                $list_of_terms .= '<option class="result-sub" value="'.$child->slug.'" '.$select.'>'. $child->name.' </option>';
            } //end foreach

        }

        /*
        * Moved this section inside your if statement. We don't want to display anything on empty terms
        */
        $list_of_terms .= '</select>';

    }
    return $list_of_terms;
}