it-swarm.dev

Como mostrar uma lista de termos hierárquicos?

Eu tenho uma taxonomia hierárquica chamada 'localizações geográficas'. Contém continentes em um primeiro nível e depois os países para cada um. Exemplo:

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

etc.

Usando get_terms () eu consegui produzir a lista completa de termos, mas os continentes se misturam com os países, em uma grande lista fixa.

Como posso produzir uma lista hierárquica como acima?

31
mike23

Use o wp_list_categories com o argumento da taxonomia, ele foi criado para criar listas de categorias hierárquicas, mas também suportará o uso de uma taxonomia personalizada.

exemplo do códice:
Exibir termos em uma taxonomia personalizada

Se a lista voltar ao normal, é possível que você só precise de um pouco de CSS para adicionar preenchimento às listas, para poder ver a estrutura hierárquica deles.

16
t31os

Eu percebo que esta é uma questão muito antiga, mas se você precisa construir um estrutura de termos, este pode ser um método útil para você:

/**
 * 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);
    }
}

O uso é o seguinte:

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

var_dump($categoryHierarchy);
40
pospi

Eu não sei de nenhuma função que faça o que você quer, mas você pode construir algo assim:

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

Eu não testei isso, mas você pode ver o que eu estou chegando. O que o código acima fará é dar apenas dois níveis

EDIT: ahh sim você pode usar wp_list_categories () para fazer o que você depois.

10
Brady

Você pode usar wp_list_categories (), com um argumento 'taxonomy'.

6
scribu

O código a seguir gerará drop-down com os termos, mas também pode gerar qualquer outro elemento/estrutura editando a variável $ outputTemplate e editando as linhas 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

Como eu estava procurando o mesmo, mas para obter os termos de um post, finalmente eu compilei isso, e funciona para mim.

O que faz :
• obtém todos os termos de um nome de taxonomia para um post específico.
• para uma taxonomia hierárquica com dois níveis (ex: nível1: 'país' e nível2: 'cidades'), ele cria um h4 com o nível1 seguido por uma lista ul de nível2 e isso para todos os itens de nível1.
• se a taxonomia não for hierárquica, criará apenas uma lista ul de todos os itens. aqui está o código (escrevo para mim, então tentei ser o mais genérico possível, mas ...):

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>';
    };
};

Então, finalmente, você chama a função com isso (obviamente, você substitui my_taxonomy pelo seu): finishingLister('my_taxonomy');

Eu não finjo que é perfeito, mas como eu disse, funciona para mim.

3
Trouille2

Eu tive esse problema e nenhuma das respostas aqui funcionou para mim, por uma razão ou outra.

Aqui está a minha versão atualizada e funcionando.

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

E uso:

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

Eu usei o código @popsi que estava funcionando muito bem e o tornei mais eficiente e fácil de ler:

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

Uso:

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