Come mostrare un elenco di termini gerarchici?


34

Ho una tassonomia gerarchica chiamata "posizioni geografiche". Contiene continenti di primo livello, quindi i paesi per ognuno. Esempio :

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

eccetera.

Usando get_terms () sono riuscito a produrre l'elenco completo dei termini, ma i continenti si confondono con i paesi, in una grande lista piatta.

Come posso generare un elenco gerarchico come sopra?


2
Nel caso in cui qualcuno abbia bisogno di una CHECKLIST gerarchica (non la domanda qui, ma relativa alle persone che creano un'interfaccia utente personalizzata per le tassonomie gerarchiche), la risposta migliore è utilizzare wp_terms_checklist () con la tassonomia personalizzata.
jerclarke,

Risposte:


19

Utilizzare wp_list_categoriescon l' 'taxonomy' => 'taxonomy'argomento, è costruito per la creazione di elenchi di categorie gerarchiche ma supporterà anche l'utilizzo di una tassonomia personalizzata.

Esempio di codice:
visualizzare i termini in una tassonomia personalizzata

Se la lista torna piatta, è possibile che tu abbia bisogno di un po 'di CSS per aggiungere il riempimento alle liste, in modo da poter vedere la loro struttura gerarchica.


Questo potrebbe essere invertito? Mostra prima i bambini ..
Arg Geo

43

Mi rendo conto, questa è una domanda molto antica, ma se hai bisogno di costruire una struttura reale di termini, questo potrebbe essere un metodo utile per te:

/**
 * 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_hierarchically(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_hierarchically($cats, $topCat->children, $topCat->term_id);
    }
}

L'utilizzo è il seguente:

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

var_dump($categoryHierarchy);

3
Questo è davvero buono. Vorrei cambiare una cosa: $into[$cat->term_id] = $cat;in $into[] = $cat;Avere l'ID del termine come chiave dell'array è fastidioso (non puoi ottenere facilmente il primo elemento usando il tasto 0) e inutile (stai già memorizzando l' $catoggetto e puoi ottenere l'id utilizzando la term_idproprietà.
Nahuel

Se come me stai provando ad applicare questa funzione a un sotto-livello di categorie, dovrai passare l'ID del livello a cui sei attualmente per farlo funzionare. Ma funziona bene, grazie @popsi.
Ben Everard,

funziona, grazie
Luca Reghellin il

10

Non conosco alcuna funzione che fa quello che vuoi ma puoi creare qualcosa del genere:

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

Non l'ho provato ma puoi vedere a cosa sto arrivando. Quello che farà il codice sopra è darti solo due livelli

EDIT: ahh sì, puoi usare wp_list_categories () per fare quello che cerchi.


In realtà questo è abbastanza utile, poiché ho bisogno di avere collegamenti personalizzati (con un parametro GET) sul termine collegamenti, che non sembra possibile con il modo wp_list_categories () di farlo.
mike23,

1
Sì, questo metodo darà un maggiore controllo sull'output. Ma potresti fare un po 'di ricerca e sostituzione sull'output di wp_list_categories()per aggiungere i tuoi parametri GET. O ancora meglio creare un filtro per la funzione da aggiungere nei bit desiderati. Non chiedermi come fai perché non sono stato ancora in grado di pensarci su :(
Brady

3
Suggerirei di utilizzare un walker di categoria personalizzato con wp_list_categoriesse desideri un maggiore controllo sull'output, renderà il tuo codice molto più riutilizzabile ..
t31os

6

Puoi usare wp_list_categories (), con un argomento "tassonomia".


3

Mentre cercavo lo stesso, ma per ottenere i termini di un post, finalmente ho compilato questo, e funziona per me.

Cosa fa:
• ottiene tutti i termini di un nome di tassonomia per un post specifico.
• per una tassonomia gerarchica con due livelli (es: livello 1: "paese" e livello 2: "città"), crea un h4 con il livello 1 seguito da un elenco ul di livello 2 e questo per tutti gli elementi di livello 1.
• se la tassonomia non è gerarchica, creerà solo un elenco ul di tutti gli elementi. ecco il codice (lo scrivo per me, quindi ho cercato di essere il più generico possibile ma ...):

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

Quindi finalmente chiami la funzione con questo (ovviamente, sostituisci my_taxonomy con la tua): finishingLister('my_taxonomy');

Non pretendo che sia perfetto, ma come ho detto, funziona per me.


3

Il seguente codice genererà il menu a discesa con i termini, ma può anche generare qualsiasi altro elemento / struttura modificando la variabile $ outputTemplate e modificando le righe 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>';  

1

Ho avuto questo problema e nessuna delle risposte qui ha funzionato per me, per una ragione o per l'altra.

Ecco la mia versione aggiornata e funzionante.

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

$selector = locationSelector('locationSelectClass');
echo $selector;

1

Ho usato il codice @popsi che funzionava davvero bene e l'ho reso più efficiente e facile da leggere:

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

Utilizzo:

$sorted_terms = sort_terms_hierarchicaly($terms);

-1

Assicurati che hierarchical=truesia passato alla tua get_terms()chiamata.

Nota che hierarchical=trueè l'impostazione predefinita, quindi davvero, assicurati solo che non sia stata ignorata false.


Ciao Chip, sì "gerarchico" è "vero" per impostazione predefinita.
mike23,

Potete fornire un collegamento ad un esempio live dell'output?
Chip Bennett,

Commentando una risposta lasciata quasi due anni fa? Veramente? In realtà, è una risposta proposta, anche se formulata come una domanda. Devo modificarlo per essere un'affermazione, piuttosto che una domanda?
Chip Bennett,

get_terms()restituirà un elenco completo dei termini (come indicato dall'OP) ma non un elenco gerarchico che mostra la relazione padre / figlio come richiesto.
jdm2112

-1

Qui ho l'elenco di selezione a discesa a quattro livelli con il primo elemento nascosto

<select name="lokalizacja" id="ucz">
            <option value="">Wszystkie lokalizacje</option>
            <?php
            $excluded_term = get_term_by('slug', 'podroze', 'my_travels_places');
            $args = array(
                'orderby' => 'slug',
                'hierarchical' => 'true',
                'exclude' => $excluded_term->term_id,
                'hide_empty' => '0',
                'parent' => $excluded_term->term_id,
            );              
            $hiterms = get_terms("my_travels_places", $args);
            foreach ($hiterms AS $hiterm) :
                echo "<option value='".$hiterm->slug."'".($_POST['my_travels_places'] == $hiterm->slug ? ' selected="selected"' : '').">".$hiterm->name."</option>\n";

                $loterms = get_terms("my_travels_places", array("orderby" => "slug", "parent" => $hiterm->term_id,'hide_empty' => '0',));
                if($loterms) :
                    foreach($loterms as $key => $loterm) :

                    echo "<option value='".$loterm->slug."'".($_POST['my_travels_places'] == $loterm->slug ? ' selected="selected"' : '').">&nbsp;-&nbsp;".$loterm->name."</option>\n";

                    $lo2terms = get_terms("my_travels_places", array("orderby" => "slug", "parent" => $loterm->term_id,'hide_empty' => '0',));
                    if($lo2terms) :
                        foreach($lo2terms as $key => $lo2term) :

                        echo "<option value='".$lo2term->slug."'".($_POST['my_travels_places'] == $lo2term->slug ? ' selected="selected"' : '').">&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;".$lo2term->name."</option>\n";



                        endforeach;
                    endif;

                    endforeach;
                endif;

            endforeach;
            ?>
         </select>
        <label>Wybierz rodzaj miejsca</label>
        <select name="rodzaj_miejsca" id="woj">
            <option value="">Wszystkie rodzaje</option>
            <?php
            $theterms = get_terms('my_travels_places_type', 'orderby=name');
            foreach ($theterms AS $term) :
                echo "<option value='".$term->slug."'".($_POST['my_travels_places_type'] == $term->slug ? ' selected="selected"' : '').">".$term->name."</option>\n";                   
            endforeach;
            ?>
         </select>

2
Spiega perché ciò potrebbe risolvere il problema.
fuxia

Penso che la logica sia che si tratti di un problema correlato. Ho trovato questo post cercando di capire come ottenere una checklist gerarchica in stile categoria e sono tentato di aggiungere una risposta qui ora che l'ho capito. Non lo farò perché, come fai notare, non risponde all'OQ.
jerclarke,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.