Як показати список ієрархічних термінів?


34

У мене є ієрархічна систематика, яка називається "географічне розташування". Він містить континенти першого рівня, а потім країни для кожного. Приклад:

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

тощо.

Використовуючи get_terms (), мені вдалося вивести повний перелік термінів, але континенти змішуються з країнами, в одному великому плоскому списку.

Як я можу вивести такий ієрархічний список, як вище?


2
Якщо комусь потрібен ієрархічний CHECKLIST (не питання тут, але стосується людей, що створюють користувальницький інтерфейс для ієрархічних таксономій), найкращою відповіддю є використання wp_terms_checklist () зі своєю власною систематикою.
jerclarke

Відповіді:


19

Використовуйте wp_list_categoriesз 'taxonomy' => 'taxonomy'аргументом, він створений для створення ієрархічних списків категорій, але також підтримуватиме використання власної таксономії.

Приклад Codex:
Відображення термінів у спеціальній систематиці

Якщо список виглядає рівним, можливо, вам просто потрібно трохи CSS, щоб додати в списки прокладки, щоб ви могли бачити їх ієрархічну структуру.


Чи можна це відмінити? Показуйте дітей першим ..
Arg Geo

43

Я усвідомлюю, що це дуже давнє питання, але якщо у вас є необхідність створити фактичну структуру термінів, це може бути корисним методом для вас:

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

Використання полягає в наступному:

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

var_dump($categoryHierarchy);

3
Це насправді дуже добре. Я змінив би одне: $into[$cat->term_id] = $cat;на $into[] = $cat;те, щоб мати ідентифікатор терміна як ключа масиву дратує (перший елемент не можна легко отримати за допомогою клавіші 0) і марний (ви вже зберігаєте $catоб'єкт і можете отримати ідентифікатор користування term_idоб'єктом нерухомості
Nahuel

Якщо ви, як я, ви намагаєтесь застосувати цю функцію до підрівневих категорій, вам потрібно буде ввести ідентифікатор рівня, на якому ви зараз перебуваєте, щоб це працювало. Але добре працює, дякує @popsi.
Бен Еверард

працює, дякую
Лука Регеллін

10

Я не знаю жодної функції, яка робить те, що ви хочете, але ви можете створити щось подібне:

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

Я цього не перевіряв, але ви можете бачити, на що я потрапляю. Згаданий вище код буде робити лише два рівні

EDIT: ага так, ви можете використовувати wp_list_categories (), щоб робити те, що ви робите після.


Насправді це дуже корисно, оскільки мені потрібно мати користувальницькі посилання (з параметром GET) на термінах посилань, що не видається можливим при wp_list_categories () способі цього зробити.
mike23

1
Так, цей метод дасть більше контролю над вашими результатами. Але ви можете зробити трохи приємного пошуку та заміни на виході, wp_list_categories()щоб додати свої параметри GET. Або ще краще побудувати фільтр для функції, яку потрібно додати в потрібні біти. Не запитуйте мене, як ви це робите, оскільки мені ще не вдалося об'їхати :(
Брейді,

3
Я запропонував би використовувати призначені для користувача категорії ходунок з , wp_list_categoriesякщо ви хочете більшого контролю над виходом, це зробить ваш код більш багаторазового використання ..
t31os

6

Ви можете використовувати wp_list_categories () з аргументом "таксономія".


3

Коли я шукав те саме, але щоб отримати умови однієї посади, нарешті я склав це, і це працює для мене.

Що це робить:
• він отримує всі умови назви таксономії для конкретної посади.
• для ієрахічної систематики з двома рівнями (наприклад: рівень1: 'країна' та рівень2: 'міста') вона створює h4 з рівнем1, а потім ul-списком рівня2 та цим для всіх елементів1 рівня.
• якщо систематика не є ієрархічною, вона створить лише ul-список усіх пунктів. ось код (я пишу його для мене, тому я намагався бути максимально загальним, але можу, але ...):

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

Отже, нарешті, ви викликаєте функцію цим (очевидно, ви замінюєте my_taxonomy на ваш): finishingLister('my_taxonomy');

Я не претендую, що це ідеально, але, як я вже сказав, це працює на мене.


3

Наступний код генерує спадне меню з термінами, але також може генерувати будь-який інший елемент / структуру, редагуючи змінну $ outputTemplate та редагуючи рядки 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

У мене була ця проблема, і жодна з відповідей тут не працювала для мене з тих чи інших причин.

Ось моя оновлена ​​та робоча версія.

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

І використання:

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

1

Я використав код @popsi, який працював дуже добре, і я зробив його більш ефективним і легким для читання:

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

Використання:

$sorted_terms = sort_terms_hierarchicaly($terms);

-1

Будьте впевнені, що hierarchical=trueце передано вашому get_terms()дзвінку.

Зауважте, що hierarchical=trueце за замовчуванням, так що дійсно, просто переконайтеся, що його не було переопрацьовано false.


Привіт Чіп, так "ієрархічна" - це "правда" за замовчуванням.
mike23

Чи можете ви надати посилання на прямий приклад результату?
Чіп Беннетт

Коментуючи відповідь, залишену майже два роки тому? Дійсно? На насправді, це є планованим відповіддю, навіть якщо сформулювати у вигляді питання. Чи потрібно редагувати це як висловлювання, а не питання?
Чіп Беннетт

get_terms()поверне повний перелік термінів (як зазначено в ОП), але не ієрархічний список із зазначенням стосунків батьків / дитини, як вимагається.
jdm2112

-1

Тут у мене є список вибору зі списку чотирьох рівнів із прихованим першим елементом

<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
Поясніть, будь ласка, чому це може вирішити проблему.
фуксія

Я думаю, що логіка полягає в тому, що це пов'язана проблема. Я знайшов цю публікацію, намагаючись зрозуміти, як отримати ієрархічний контрольний список у стилі категорії, і я спокусився додати відповідь сюди зараз, коли я це зрозумів. Я не хочу, тому що, як ви вказуєте, він не відповідає OQ.
jerclarke
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.