Comment ne lister que les termes enfant d'une taxonomie et non leurs parents?

9

Je crée un menu de sélection d'âge dans l'administrateur, rempli à partir d'une taxonomie de age. La taxonomie est hiérarchique comme suit:

  • 18-25 (parent, ID 183)
    • 18 (enfant)
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 26-30 (parent, ID 184)
    • 26
    • 27
    • 28
    • 29
    • 30

Je voudrais seulement lister les enfants (18, 19 etc) et non les parents (18-25, 26-30) etc. Actuellement, j'utilise get_termsl' parentargument, mais il n'accepte pas plus d'une ID parent. Voici ce que j'ai jusqu'à présent, qui montre les enfants de 18 à 25 ans.

    $ages = get_terms( 'age', array(
        'hide_empty' => 0,
        'parent' => '183',
    ));

Voici ce que je veux qu'il fasse, mais n'est pas pris en charge. Je l'ai également essayé avec un tableau mais cela ne fonctionne pas non plus.

    $ages = get_terms( 'age', array(
        'hide_empty' => 0,
        'parent' => '183,184',
    ));

Je vois qu'il y a une fonction get_term_children mais je ne suis pas sûr de savoir comment l'utiliser, car il semble qu'il n'accepte qu'une seule valeur également. Par exemple: Dans cet exemple, il créerait une liste non ordonnée mais je pourrais modifier pour sélectionner le menu.

<?php
    $termID = 183;
    $taxonomyName = "age";
    $termchildren = get_term_children( $termID, $taxonomyName );

    echo '<ul>';
    foreach ($termchildren as $child) {
    $term = get_term_by( 'id', $child, $taxonomyName );
    echo '<li><a href="' . get_term_link( $term->name, $taxonomyName ) . '">' . $term->name . '</a></li>';
    }
    echo '</ul>';
?> 
Andrew
la source
Appelez get_termsdeux fois et fusionnez les deux tableaux de résultats?
Mark Duncan
@Mark Merci, j'ai pensé à le faire de cette façon, mais même si je fusionne les identifiants dans un tableau, je ne vois pas comment cela fonctionnerait car cela reviendrait à les répertorier manuellement - 183, 184, ce qui ne fonctionne pas. t travailler.
Andrew
Après avoir lu la réponse acceptée, je réalise maintenant que votre question n'était pas tout à fait claire, à en juger par les choses que vous vouliez tous les termes, à l'exclusion des termes de haut niveau .. (ce que vous pouvez faire avec un seul get_termsappel). Votre question se lit comme si vous vouliez tous les enfants de 2 termes parentaux particuliers.
Mark Duncan

Réponses:

14

Cela devrait fonctionner pour vous:

$taxonomyName = "age";
//This gets top layer terms only.  This is done by setting parent to 0.  
$parent_terms = get_terms( $taxonomyName, array( 'parent' => 0, 'orderby' => 'slug', 'hide_empty' => false ) );   
echo '<ul>';
foreach ( $parent_terms as $pterm ) {
    //Get the Child terms
    $terms = get_terms( $taxonomyName, array( 'parent' => $pterm->term_id, 'orderby' => 'slug', 'hide_empty' => false ) );
    foreach ( $terms as $term ) {
        echo '<li><a href="' . get_term_link( $term ) . '">' . $term->name . '</a></li>';   
    }
}
echo '</ul>';
Manny Fleurmond
la source
Merci @Manny, a travaillé un régal. J'ai pris ce que vous avez fourni et l'ai écrasé dans le menu de sélection que je recherchais. Super truc.
Andrew
Aucun problème. Heureux que cela ait fonctionné pour vous.
Manny Fleurmond
1
Voir la réponse de karimhossenbux ci-dessous pour une réponse beaucoup plus efficace.
dotancohen
$term->namen'est pas valide dans get_term_link(), il n'accepte que le terme ID, slug ou object
Pieter Goosen
14

Vous pourriez également faire:

$terms = get_terms($taxonomyName);
foreach($terms as $term) {
    if ($term->parent != 0) { // avoid parent categories
        //your instructions here
    }
}

J'ai remarqué que le parent a un champ "parent" égal à 0 et qu'un enfant a son identifiant parent.

karimhossenbux
la source
4
La réponse acceptée exécute N appels get_terms () et s'exécute en temps polynomial. Cette réponse exécute un seul appel get_terms () et s'exécute en temps linéaire. C'est une bien meilleure réponse.
dotancohen
@dotancohen Vous pouvez le faire sans avoir à exclure les termes de niveau supérieur sur la sortie, vous pouvez supprimer les termes de niveau supérieur avec le wpse_exclude_topparamètre ajouté aux arguments de la requête ;-). Je suis cependant d'accord, c'est plus rapide que la réponse acceptée
Pieter Goosen
1
@PieterGoosen: Merci Pieter. Je viens de saluer le code source 4.4.2 pour les chaînes wpse_exclude_topet je ne les ai pas trouvées exclude_top. Google ne le sait pas non plus . Où est-il documenté?
dotancohen
1
@dotancohen dans ma réponse ;-)
Pieter Goosen
5

Nous pouvons exclure les parents de niveau supérieur en les filtrant en utilisant le terms_clausesfiltre pour modifier la requête SQL avant son exécution. De cette façon, nous n'avons pas besoin d'ignorer les parents dans la foreachboucle finale car ils ne sont pas dans le tableau de termes retourné, cela nous évite un travail et un codage inutiles

Vous pouvez essayer ce qui suit:

add_filter( 'terms_clauses', function (  $pieces, $taxonomies, $args )
{
    // Check if our custom arguments is set and set to 1, if not bail
    if (    !isset( $args['wpse_exclude_top'] ) 
         || 1 !== $args['wpse_exclude_top']
    )
        return $pieces;

    // Everything checks out, lets remove parents
    $pieces['where'] .= ' AND tt.parent > 0';

    return $pieces;
}, 10, 3 );

Pour exclure les parents de niveau supérieur, nous pouvons maintenant passer 'wpse_exclude_top' => 1avec notre tableau d'arguments. Le nouveau wpse_exclude_topparamètre est pris en charge par le filtre ci-dessus

$terms = get_terms( 'category', ['wpse_exclude_top' => 1] );
if (    $terms
     && !is_wp_error( $terms )
) {
    echo '<ul>';
        foreach ($terms as $term) {
            echo '<li><a href="' . get_term_link( $term ) . '">' . $term->name . '</a></li>';  
        }
    echo '</ul>';
}

Juste une note, get_term_link()n'acceptez pas le nom du terme, seulement, slug, ID ou l'objet terme complet. Pour les performances, transmettez toujours toujours l'objet terme à get_term_link()si l'objet terme est disponible ( comme dans ce cas )

Pieter Goosen
la source
2

Pourquoi ne pouvez-vous pas simplement définir l' childlessargument sur vrai?

$ages = get_terms( array(
    'taxonomy' => 'age',
    'childless' => true
    )
);
Yaron
la source
définir l' childlessargument sur true signifie que vous ne pouvez aller qu'à un niveau, donc cela ne fonctionne pas pour les taxonomies à 3 niveaux ou plus.
GeckoSEO
-1

Si vous affichez l'enfant de plusieurs parents, vous pouvez essayer ceci. Afficher mention terme terme enfant terme.

$termIds = array(367, 366, 365, 364, 363, 362);
$taxonomyName = "age";

$args = array(
    'orderby'           => 'term_id', 
    'order'             => 'DESC',                      
    'hide_empty'        => false,                       
    'childless'         => false,
); 

$terms = get_terms( $taxonomyName, $args );

if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
$inc = 1;
foreach ( $terms as $term ) {                           
 if (in_array($term->parent, $termIds)) {
  echo '<option value="'.$term->term_id.'"><font><font>'.$term->name.'</font></font></option>';
    }
  }
}
Jakir Hossain
la source
1
Veuillez expliquer pourquoi vous pensez que ce code devrait fonctionner. De plus, je suis presque sûr qu'une solution codée en dur n'est pas la meilleure solution.
s_ha_dum
La question mentionne avec des identifiants, pour cette raison, j'ai répondu à une réflexion connexe.
Jakir Hossain