web-dev-qa-db-fra.com

Obtenez des enfants directs de taxonomie personnalisée

J'ai beaucoup cherché sur Google et fait de mon mieux, mais je ne peux tout simplement pas faire fonctionner les enfants de premier niveau de la taxonomie personnalisée dans le code ci-dessous! Il affiche uniquement le niveau parent. Ce que j'essaie de réaliser est le suivant:

Level 1  <--- at the moment, it only displays this level
  Level 2  <-- I want to display this level too
    Level 3  <-- but NOT this level

Ceci est mon code jusqu'à présent:

function my_dropdown_categories( $taxonomy, $current_selected = '', $include = null ) {
// Get all terms of the chosen taxonomy
$terms = get_terms($taxonomy, array('orderby' => 'name'));

// our content variable
$list_of_terms = '<select id="location" class="selectboxSingle" name="location">';

if ( ! is_wp_error( $terms ) ) 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: ==

if ($term->parent == 0 ) {

    // get children of current parent.
    // $tchildren = get_term_children($term->term_id, $taxonomy); <- gets ALL children

    $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);

    // 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
  }
}

$list_of_terms .= '</select>';

return $list_of_terms;
}

Si quelqu'un peut m'aider avec cette bête, vous serez mon héros terrifiant!

EDIT(plus d'informations basées sur la réponse de Pieter):

Ceci est ce qui est en cours de sortie (tous les parents):

Parent 1

--Parent 1

--Parent 2

--Parent 3

--Parent 4

Parent 2

--Parent 2

--Parent 1

--Parent 3

etc

1
Guit4eva

Vous avez deux problèmes ici, l'un est un problème de performances, l'autre est un gros problème qui devrait renvoyer une pile d'erreurs si vous activez le débogage

Le problème de performances ici est votre première instance où vous obtenez les termes. Il semble que votre objectif ici soit d'obtenir uniquement des termes de premier niveau, mais vous obtenez tout. J'ajouterais simplement 'parent' => 0 aux arguments pour obtenir uniquement les termes de premier niveau. Vous pouvez ensuite supprimer la condition dans laquelle vous cochez if ( $term->parent == 0 ) car tous les termes seront des termes de niveau supérieur qui auront tous 0 comme terme parent; cette condition sera donc toujours vraie.

Votre gros problème est avec ce code, et je ne comprends pas votre logique ici

    $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);

Vous avez raison d’obtenir votre terme direct enfants, votre déclaration de $uchildren convient donc. À partir de là, tout se passe mal

  • Pourquoi utilisez-vous get_term_by() here. $child contient déjà les propriétés du terme car vous avez utilisé get_terms() pour récupérer les termes.

  • Vous n'utilisez pas simplement get_term_by() à tort ici, mais vos arguments ne sont pas valides et vous lui transmettez également un objet complet. Vous devriez consulter le codex pour utiliser correctement cette fonction. Dans l’ensemble, cette section devrait être supprimée de votre code

Cette section devrait ressembler à quelque chose comme ça

    $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);

MODIFIER

Voici un code de travail complet avec quelques bugs corrigés. S'il vous plaît voir mes commentaires dans le code pour les mises à jour

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;
}
3
Pieter Goosen

Vérifiez ce code

$uchildren =get_terms( 'category', array('hide_empty' => false, '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;
}

Cette ligne

$cterm = get_term_by( 'id', $child, $taxonomy ); 

suppose que $ enfant sera un identifiant (et un entier), alors que:

foreach ($uchildren as $child) {

nous donne un objet

C'est aussi la raison pour laquelle cela ne fonctionne pas comme vous le souhaitez:

if ( is_array( $include ) && ! in_array( $cterm->slug, $include ) ) continue;

De là, c'est de la camelote que j'avais postée mais le bon sens a prévalu jusqu'à ce que ...

Faisons la partie amusante:

var_dump($term):

Notez le type de chaque propriété:

object(stdClass)(9) {
    ...
    ["parent"]=>
    string(1) "0"
    ...
}

Voir la parent. C'est une ficelle. Je sais, logiquement, cela devrait être un entier, mais c'est une chaîne. C'est nul, non!

Donc, votre condition if ($term->parent == 0 ) { n'est pas satisfaite. Essayez ceci à la place:

if ( empty( $term->parent ) ) {

ici

0
Saurabh Shukla