Jak wyświetlić hierarchiczną listę terminów?


34

Mam hierarchiczną taksonomię zwaną „lokalizacjami geograficznymi”. Zawiera kontynenty na pierwszym poziomie, a następnie kraje dla każdego z nich. Przykład:

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

itp.

Za pomocą get_terms () udało mi się wypisać pełną listę terminów, ale kontynenty mieszają się z krajami, w jednej dużej płaskiej liście.

Jak wygenerować hierarchiczną listę jak wyżej?


2
Jeśli ktoś potrzebuje hierarchicznej LISTY KONTROLNEJ (nie pytania tutaj, ale odnoszą się do osób budujących niestandardowy interfejs użytkownika dla hierarchicznych taksonomii), najlepszą odpowiedzią jest użycie wp_terms_checklist () z niestandardową taksonomią.
— jerclarke

Odpowiedzi:


19

Użyj wp_list_categoriesz 'taxonomy' => 'taxonomy'argumentem, jest zbudowany do tworzenia hierarchicznych list kategorii, ale będzie również obsługiwał niestandardową systematykę.

Przykład Kodeksu:
Wyświetl warunki w niestandardowej taksonomii

Jeśli lista wróci i wygląda płasko, możliwe jest, że wystarczy trochę CSS, aby dodać dopełnienie do list, aby zobaczyć ich hierarchiczną strukturę.


Czy można to odwrócić? Pokaż dzieci jako pierwsze ..
— Arg Geo

43

Zdaję sobie sprawę, że jest to bardzo stare pytanie, ale jeśli musisz zbudować rzeczywistą strukturę terminów, może to być przydatna metoda:

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

Użycie jest następujące:

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

var_dump($categoryHierarchy);

3
To jest naprawdę bardzo dobre. Zmieniłbym jedną rzecz: $into[$cat->term_id] = $cat;na $into[] = $cat;Posiadanie identyfikatora terminu, ponieważ klucz tablicy jest denerwujący (nie można łatwo uzyskać pierwszego elementu za pomocą klawisza 0) i jest bezużyteczny (przechowuje się już $catobiekt i można uzyskać identyfikator korzystając z term_idnieruchomości
— Nahuel

Jeśli podobnie jak ja próbujesz zastosować tę funkcję do podrzędnego poziomu kategorii, musisz przekazać identyfikator poziomu, na którym obecnie jesteś, aby to zadziałało. Ale działa ładnie, dzięki @popsi.
— Ben Everard,

to działa, dziękuję
— Luca Reghellin

10

Nie znam żadnej funkcji, która robi to, co chcesz, ale możesz zbudować coś takiego:

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

Nie testowałem tego, ale widać, o co mi chodzi. Powyższy kod da ci tylko dwa poziomy

EDYCJA: ahh tak, możesz użyć wp_list_categories () do robienia tego, co chcesz.


W rzeczywistości jest to dość przydatne, ponieważ muszę mieć niestandardowe linki (z parametrem GET) w terminach links, co nie wydaje się możliwe w przypadku sposobu wp_list_categories ().
— mike23

1
Tak, ta metoda da większą kontrolę nad twoją produkcją. Ale możesz zrobić trochę miłego wyszukiwania i zamiany na wyjściu, wp_list_categories()aby dodać parametry GET. Lub jeszcze lepiej zbuduj filtr dla funkcji, aby dodać żądane bity. Nie pytaj mnie, jak to robisz, ponieważ nie byłem jeszcze w stanie tego ogarnąć :(
— Brady,

3
Sugeruję użyciu niestandardowych kategorii chodzika ze wp_list_categoriesjeśli chcesz większą kontrolę nad wyjściem, będzie to zrobić znacznie więcej kodu wielokrotnego użytku ..
— t31os

6

Możesz użyć wp_list_categories () z argumentem „taksonomia”.


3

Ponieważ szukałem tego samego, ale aby uzyskać warunki jednego posta, w końcu skompilowałem to i działa dla mnie.

Co robi:
• otrzymuje wszystkie warunki nazwy taksonomicznej dla określonego stanowiska.
• dla taksonomii hierarchicznej z dwoma poziomami (np. Poziom 1: „kraj” i poziom 2: „miasta”), tworzy h4 z poziomem 1, po którym następuje lista ul poziomu 2 i to dla wszystkich elementów poziomu 1.
• jeśli taksonomia nie jest hierarchiczna, utworzy tylko listę ul wszystkich pozycji. oto kod (piszę go dla siebie, więc starałem się być tak ogólny, jak tylko potrafię, ale ...):

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

Więc w końcu wywołujesz funkcję w ten sposób (oczywiście zamieniasz my_taxonomy na swój): finishingLister('my_taxonomy');

Nie udaje, że jest idealny, ale jak powiedziałem, działa dla mnie.


3

Poniższy kod wygeneruje listę rozwijaną z terminami, ale może również wygenerować dowolny inny element / strukturę, edytując zmienną $ outputTemplate i edytując linie 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

Miałem ten problem i żadna z odpowiedzi tutaj nie działała dla mnie z tego czy innego powodu.

Oto moja zaktualizowana i działająca wersja.

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

I użycie:

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

1

Użyłem kodu @popsi, który działał naprawdę dobrze i uczyniłem go bardziej wydajnym i łatwym do odczytania:

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

Stosowanie :

$sorted_terms = sort_terms_hierarchicaly($terms);

-1

Upewnij się, że hierarchical=truezostał przekazany do twojego get_terms()połączenia.

Pamiętaj, że hierarchical=truejest to ustawienie domyślne, więc naprawdę upewnij się, że nie zostało to nadpisane false.


Cześć Chip, tak, domyślnie „hierarchiczny” to „prawda”.
— mike23

Czy możesz podać link do przykładowego wyjścia?
— Chip Bennett

Komentujesz odpowiedź pozostawioną prawie dwa lata temu? Naprawdę? W rzeczywistości jest to proponowana odpowiedź, nawet sformułowana jako pytanie. Czy powinienem edytować to, aby było stwierdzeniem, a nie pytaniem?
— Chip Bennett

get_terms()zwróci pełną listę warunków (jak stwierdził PO), ale nie hierarchiczną listę pokazującą relacje rodzic / dziecko zgodnie z żądaniem.
— jdm2112

-1

Tutaj mam czteropoziomową listę wyboru z ukrytym pierwszym elementem

<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
Proszę wyjaśnić, dlaczego to może rozwiązać problem.
— fuxia

Myślę, że logika jest związana z tym problemem. Znalazłem ten post, próbując dowiedzieć się, jak uzyskać hierarchiczną listę kontrolną w stylu kategorii i kusi mnie, aby dodać odpowiedź teraz, kiedy to wymyśliłem. Nie zrobię tego, ponieważ, jak zauważyłeś, nie odpowiada OQ.
— jerclarke
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.