mike
  • 0
Гуру

Как отобразить иерархический список терминов?

  • 0

У меня есть иерархическая таксономия под названием «географические местоположения». Он содержит континенты на первом уровне, а затем страны для каждого из них. Пример :

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

и т.п.

Используя get_terms(), мне удалось вывести полный список терминов, но континенты перепутались со странами в одном большом плоском списке.

Как я могу вывести иерархический список, как указано выше?

Share
  1. В случае, если кому-то нужен иерархический КОНТРОЛЬНЫЙ СПИСОК (не вопрос здесь, а связанный с людьми, создающими собственный пользовательский интерфейс для иерархических таксономий), лучшим ответом будет использование wp_terms_checklist() с вашей пользовательской таксономией.

    • 0
  2. Используйте wp_list_categories с 'taxonomy' => 'taxonomy' аргументом, он создан для создания иерархических списков категорий, но также поддерживает использование пользовательской таксономии.

    Пример Кодекса:
    отображение терминов в пользовательской таксономии

    Если список снова выглядит плоским, возможно, вам просто нужно немного CSS, чтобы добавить отступы к спискам, чтобы вы могли видеть их иерархическую структуру.

    • 0
  3. Я понимаю, что это очень старый вопрос, но если вам нужно создать реальную структуру терминов, это может быть для вас полезным методом:

    /**
     * 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);
    
    • 0
  4. Я не знаю ни одной функции, которая делает то, что вы хотите, но вы можете создать что-то вроде этого:

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

    Я не проверял это, но вы можете видеть, к чему я клоню. Приведенный выше код даст вам только два уровня.

    РЕДАКТИРОВАТЬ: ааа, да, вы можете использовать wp_list_categories(), чтобы делать то, что вам нужно.

    • 0
  5. Вы можете использовать wp_list_categories() с аргументом «таксономия».

    • 0
  6. Следующий код сгенерирует раскрывающийся список с терминами, но также может сгенерировать любой другой элемент/структуру, отредактировав переменную $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>';  
    
    • 0
  7. Я использовал код @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);
    
    • 0
  8. Поскольку я искал то же самое, но чтобы получить условия одного поста, наконец, я собрал это, и это работает для меня.

    Что он делает:
    • получает все термины имени таксономии для определенного поста.
    • для иерархической таксономии с двумя уровнями (например, уровень 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');

    Я не претендую на то, что это идеально, но, как я уже сказал, это работает для меня.

    • 0
  9. У меня была эта проблема, и ни один из ответов здесь не помог мне по той или иной причине.

    Вот моя обновленная и рабочая версия.

    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;
    
    • 0
  10. Это решение менее эффективно, чем код @popsi, поскольку оно создает новый запрос для каждого термина, но его также проще использовать в шаблоне. Если ваш веб-сайт использует кэширование, вы, как и я, можете не возражать против небольших накладных расходов на базу данных.

    Вам не нужно готовить массив, который будет рекурсивно заполняться терминами. Вы просто вызываете его так же, как и get_terms() (не устаревшая форма с только массивом в качестве аргумента). Он возвращает массив WP_Term объектов с дополнительным свойством, называемым children .

    function get_terms_tree( Array $args ) {
        $new_args = $args;
        $new_args['parent'] = $new_args['parent'] ?? 0;
        $new_args['fields'] = 'all';
    
        // The terms for this level
        $terms = get_terms( $new_args );
    
        // The children of each term on this level
        foreach( $terms as &$this_term ) {
            $new_args['parent'] = $this_term->term_id;
            $this_term->children = get_terms_tree( $new_args );
        }
    
        return $terms;
    }
    

    Использование простое:

    $terms = get_terms_tree([ 'taxonomy' => 'my-tax' ]);
    
    • 0
  11. Будьте уверены, что hierarchical=true передается на ваш get_terms() вызов.

    Обратите внимание, что hierarchical=true это значение по умолчанию, так что на самом деле просто убедитесь, что оно не было изменено на false .

    • 0
  12. Здесь у меня есть четырехуровневый раскрывающийся список выбора со скрытым первым элементом.

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

Оставить ответ

You must login to add an answer.