web-dev-qa-db-fra.com

Comment afficher une liste de termes hiérarchiques?

J'ai une taxonomie hiérarchique appelée "lieux géographiques". Il contient les continents sur un premier niveau, puis les pays pour chacun. Exemple :

Europe
- Ireland
- Spain
- Sweden
Asia
- Laos
- Thailand
- Vietnam

etc.

En utilisant get_terms (), j’ai réussi à afficher la liste complète des termes, mais les continents se confondent avec les pays, dans une grande liste à plat.

Comment puis-je sortir une liste hiérarchique comme ci-dessus?

31
mike23

Utilisez wp_list_categories avec l'argument taxonomy, il est conçu pour créer des listes de catégories hiérarchiques, mais prend également en charge l'utilisation d'une taxonomie personnalisée.

Exemple Codex:
Afficher les termes dans une taxonomie personnalisée

Si la liste revient à plat, il est possible que vous ayez juste besoin d'un peu de CSS pour ajouter du padding aux listes afin que vous puissiez voir leur structure hiérarchique.

16
t31os

Je me rends compte que c’est une très vieille question, mais si vous avez besoin de construire une structure termes réelle, cela pourrait être une méthode utile pour vous:

/**
 * Recursively sort an array of taxonomy terms hierarchically. Child categories will be
 * placed under a 'children' member of their parent term.
 * @param Array   $cats     taxonomy term objects to sort
 * @param Array   $into     result array to put them in
 * @param integer $parentId the current parent ID to put them in
 */
function sort_terms_hierarchicaly(Array &$cats, Array &$into, $parentId = 0)
{
    foreach ($cats as $i => $cat) {
        if ($cat->parent == $parentId) {
            $into[$cat->term_id] = $cat;
            unset($cats[$i]);
        }
    }

    foreach ($into as $topCat) {
        $topCat->children = array();
        sort_terms_hierarchicaly($cats, $topCat->children, $topCat->term_id);
    }
}

L'utilisation est la suivante:

$categories = get_terms('my_taxonomy_name', array('hide_empty' => false));
$categoryHierarchy = array();
sort_terms_hierarchicaly($categories, $categoryHierarchy);

var_dump($categoryHierarchy);
40
pospi

Je ne connais aucune fonction qui fasse ce que vous voulez, mais vous pouvez construire quelque chose comme ceci:

<ul>
    <?php $hiterms = get_terms("my_tax", array("orderby" => "slug", "parent" => 0)); ?>
    <?php foreach($hiterms as $key => $hiterm) : ?>
        <li>
            <?php echo $hiterm->name; ?>
            <?php $loterms = get_terms("my_tax", array("orderby" => "slug", "parent" => $hiterm->term_id)); ?>
            <?php if($loterms) : ?>
                <ul>
                    <?php foreach($loterms as $key => $loterm) : ?>
                        <li><?php echo $loterm->name; ?></li>
                    <?php endforeach; ?>
                </ul>
            <?php endif; ?>
        </li>
    <?php endforeach; ?>
</ul>

Je n'ai pas testé cela, mais vous pouvez voir où je veux en venir. Le code ci-dessus ne vous donnera que deux niveaux.

EDIT: ahh oui, vous pouvez utiliser wp_list_categories () pour faire ce que vous voulez.

10
Brady

Vous pouvez utiliser wp_list_categories () avec un argument 'taxonomy'.

6
scribu

Le code suivant générera une liste déroulante avec les termes, mais peut également générer tout autre élément/structure en modifiant la variable $ outputTemplate et en modifiant les lignes str_replace:

function get_terms_hierarchical($terms, $output = '', $parent_id = 0, $level = 0) {
    //Out Template
    $outputTemplate = '<option value="%ID%">%PADDING%%NAME%</option>';

    foreach ($terms as $term) {
        if ($parent_id == $term->parent) {
            //Replacing the template variables
            $itemOutput = str_replace('%ID%', $term->term_id, $outputTemplate);
            $itemOutput = str_replace('%PADDING%', str_pad('', $level*12, '&nbsp;&nbsp;'), $itemOutput);
            $itemOutput = str_replace('%NAME%', $term->name, $itemOutput);

            $output .= $itemOutput;
            $output = get_terms_hierarchical($terms, $output, $term->term_id, $level + 1);
        }
    }
    return $output;
}

$terms = get_terms('taxonomy', array('hide_empty' => false));
$output = get_terms_hierarchical($terms);

echo '<select>' . $output . '</select>';  
3
wesamly

Comme je cherchais la même chose, mais pour obtenir les conditions d'un poste, je l'ai finalement compilé, et cela fonctionne pour moi.

Ce qu'il fait :
• il obtient tous les termes d'un nom de taxonomie pour un poste spécifique.
• pour une taxonomie hiérarchique à deux niveaux (ex: niveau1: 'pays' et niveau2: 'villes'), il crée un h4 avec le niveau1 suivi d'une liste ul de niveau2 et ceci pour tous les éléments de niveau1.
• si la taxonomie n'est pas hiérarchique, elle ne créera qu'une liste ul de tous les éléments. voici le code (je l’écris pour moi alors j’ai essayé d’être aussi générique que possible mais ...):

function finishingLister($heTerm){
    $myterm = $heTerm;
    $terms = get_the_terms($post->ID,$myterm);
    if($terms){
        $count = count($terms);
        echo '<h3>'.$myterm;
        echo ((($count>1)&&(!endswith($myterm, 's')))?'s':"").'</h3>';
        echo '<div class="'.$myterm.'Wrapper">';
        foreach ($terms as $term) {
            if (0 == $term->parent) $parentsItems[] = $term;
            if ($term->parent) $childItems[] = $term; 
        };
        if(is_taxonomy_hierarchical( $heTerm )){
            foreach ($parentsItems as $parentsItem){
                echo '<h4>'.$parentsItem->name.'</h4>';
                echo '<ul>';
                foreach($childItems as $childItem){
                    if ($childItem->parent == $parentsItem->term_id){
                        echo '<li>'.$childItem->name.'</li>';
                    };
                };
                echo '</ul>';
            };
        }else{
            echo '<ul>';
            foreach($parentsItems as $parentsItem){
                echo '<li>'.$parentsItem->name.'</li>';
            };
            echo '</ul>';
        };
        echo '</div>';
    };
};

Alors finalement, vous appelez la fonction avec ceci (évidemment, vous remplacez my_taxonomy par le vôtre): finishingLister('my_taxonomy');

Je ne prétends pas que c'est parfait, mais comme je l'ai dit, cela fonctionne pour moi.

3
Trouille2

J'ai eu ce problème et aucune des réponses ici ne fonctionnait pour moi, pour une raison ou une autre.

Voici ma version mise à jour et de travail.

function locationSelector( $fieldName ) {
    $args = array('hide_empty' => false, 'hierarchical' => true, 'parent' => 0); 
    $terms = get_terms("locations", $args);

    $html = '';
    $html .= '<select name="' . $fieldName . '"' . 'class="chosen-select ' . $fieldName . '"' . '>';
        foreach ( $terms as $term ) {
            $html .= '<option value="' . $term->term_id . '">' . $term->name . '</option>';

            $args = array(
                'hide_empty'    => false, 
                'hierarchical'  => true, 
                'parent'        => $term->term_id
            ); 
            $childterms = get_terms("locations", $args);

            foreach ( $childterms as $childterm ) {
                $html .= '<option value="' . $childterm->term_id . '">' . $term->name . ' > ' . $childterm->name . '</option>';

                $args = array('hide_empty' => false, 'hierarchical'  => true, 'parent' => $childterm->term_id); 
                $granchildterms = get_terms("locations", $args);

                foreach ( $granchildterms as $granchild ) {
                    $html .= '<option value="' . $granchild->term_id . '">' . $term->name . ' > ' . $childterm->name . ' > ' . $granchild->name . '</option>';
                }
            }
        }
    $html .=  "</select>";

    return $html;
}

Et utilisation:

$selector = locationSelector('locationSelectClass');
echo $selector;
1
Joe Tannorella

J'ai utilisé le code @popsi qui fonctionnait très bien et je l'ai rendu plus efficace et plus facile à lire:

/**
 * Recursively sort an array of taxonomy terms hierarchically. Child categories will be
 * placed under a 'children' member of their parent term.
 * @param Array   $cats     taxonomy term objects to sort
 * @param integer $parentId the current parent ID to put them in
 */
function sort_terms_hierarchicaly(Array $cats, $parentId = 0)
{
    $into = [];
    foreach ($cats as $i => $cat) {
        if ($cat->parent == $parentId) {
            $cat->children = sort_terms_hierarchicaly($cats, $cat->term_id);
            $into[$cat->term_id] = $cat;
        }
    }
    return $into;
}

Utilisation:

$sorted_terms = sort_terms_hierarchicaly($terms);
1
Pierre R