我有一个称为“地理位置”的层次分类法。它首先包含大洲,然后是每个大洲的国家。示例:

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


等。

使用get_terms()我设法输出了完整的术语表,但是各大洲的混淆这些国家,放在一个大的固定列表中。

如何输出上面的分层列表?

评论

如果有人需要分层的CHECKLIST(不是这里的问题,而是与为分层分类法构建自定义UI的人有关),最好的答案是将wp_terms_checklist()与自定义分类法一起使用。

#1 楼

wp_list_categories'taxonomy' => 'taxonomy'参数一起使用,它是为创建层次结构类别列表而构建的,但还将支持使用自定义分类法。.
Codex示例:在自定义分类法中显示术语
如果列表返回看起来很平坦,则可能只需要一些CSS就可以在列表中添加填充,以便可以看到其层次结构。

评论


这可以逆转吗?首先显示孩子。

– Arg Geo
16 Mar 6 '16 at 7:57

#2 楼

我知道,这是一个非常老的问题,但是如果您需要建立一个实际的术语结构,那么这可能对您有用:

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


评论


这实际上是非常好的。我将更改一件事:$ into [$ cat-> term_id] = $ cat;进入$ into [] = $ cat;将术语的ID作为数组的键很烦人(使用0键无法轻松获得第一个元素)并且毫无用处(您已经存储了$ cat对象,并且可以使用term_id属性获取ID。

–纳乌埃尔
17 Mar 7 '17 at 15:03

如果像我一样,您正在尝试将此功能应用于类别的子级别,则需要传递当前所在级别的ID才能起作用。但是工作得很好,谢谢@popsi。

– Ben Everard
18年8月16日在10:19

可行,谢谢

–路卡·雷格尔林(Luca Reghellin)
19年11月12日在16:35

#3 楼

我不知道有什么功能可以满足您的需求,但是您可以构建如下所示的东西:

<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()来完成之后的工作。

评论


实际上,这非常有用,因为我需要在术语链接上使用自定义链接(带有GET参数),而使用wp_list_categories()的方式似乎无法实现。

–mike23
2011年4月13日在15:04

是的,此方法将更好地控制您的输出。但是您可以对wp_list_categories()的输出进行一些很好的查找和替换,以添加到GET参数中。甚至更好地为该函数构建一个过滤器,以添加所需的位。不要问我你怎么做,因为我还没弄清楚它:(

–斯科特
2011年4月13日在15:19

如果您想更好地控制输出,建议您将自定义类别浏览器与wp_list_categories一起使用,这将使您的代码更具可重用性。

– t31os
2011年4月13日在16:09

#4 楼

您可以将wp_list_categories()与“分类”参数一起使用。

#5 楼

以下代码将生成带术语的下拉列表,但还可以通过编辑$ 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>';  


#6 楼

当我一直在寻找相同的内容但要获得一篇文章的条款时,最终我对其进行了编译,并且对我有用。

它的作用:
•它获得了分类法的所有条款
•对于具有两个级别的层次分类法(例如:level1:“国家”和level2:“城市”),它将创建一个带有level1的h4,后跟ul的level2列表适用于所有第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');

我并不假装它是完美的,但正如我说的那样对我有用。

#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);


#8 楼

我遇到了这个问题,由于某种原因或其他原因,这里的所有答案均无济于事。

这是我的更新版和正常工作版本。

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;


#9 楼

该解决方案的效率比@popsi的代码低,因为它会对每个术语进行新查询,但在模板中使用起来也更容易。如果您的网站使用缓存,那么像我一样,您可能不介意数据库的微小开销。

您不需要准备一个将用术语递归填充的数组。您只需以与调用get_terms()相同的方式来调用它(不推荐使用的形式,只有一个参数数组)。它返回一个带有附加属性WP_Termchildren对象数组。

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' ]);


#10 楼

请确保将hierarchical=true传递给您的get_terms()调用。

请注意,hierarchical=true是默认设置,因此,实际上,请确保未将其重写为false

评论


嗨,Chip,是的,“ hierarchical”默认为“ true”。

–mike23
2011年4月13日在14:37

您能否提供到输出示例的链接?

–芯片Bennett
2011年4月13日在14:44

评论将近两年前留下的答案?真?实际上,即使措辞是问题,这也是建议的答案。我应该将其编辑为陈述而不是问题吗?

–芯片Bennett
13年2月11日在23:22

get_terms()将返回条款的完整列表(如OP所述),但不会按层次结构列表显示要求的父/子关系。

– jdm2112
16 Mar 17 '16 at 5:00

#11 楼

在这里,我有四个级别的下拉选择列表,其中包含隐藏的第一项

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


评论


请解释为什么这可以解决问题。

– fuxia♦
2013年3月25日10:00

我认为逻辑是这是一个相关的问题。我发现这篇文章试图弄清楚如何获得一个类别样式的分层清单,并且由于我已经弄清楚了,所以很想在这里添加答案。我不会,因为正如您所指出的那样,它并没有回答OQ。

– jerclarke
16-2-23在16:26