如何显示层次化的术语列表?

时间:2011-04-13 作者:mike23

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

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

使用get\\u terms()我成功地输出了完整的术语列表,但在一个大的平面列表中,大陆与国家混淆了。

如何输出如上所述的层次列表?

11 个回复
最合适的回答,由SO网友:t31os 整理而成

使用wp_list_categories 使用\'taxonomy\' => \'taxonomy\' 参数,它是为创建分层类别列表而构建的,但也支持使用自定义分类法。。

Codex Example:
Display terms in a custom taxonomy

如果列表看起来是平面的,那么您可能只需要一点CSS来为列表添加填充,这样您就可以看到它们的层次结构。

SO网友:pospi

我意识到,这是一个非常古老的问题,但如果您需要建立一个实际的术语结构,这可能是一个有用的方法:

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

SO网友:Scott

我不知道有什么函数可以满足您的需要,但您可以构建如下内容:

<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\\u list\\u categories()来完成之后的操作。

SO网友:scribu

您可以使用wp\\u list\\u categories(),并带有“taxonomy”参数。

SO网友:wesamly

以下代码将生成包含术语的下拉列表,但也可以通过编辑$outputTemplate变量和编辑str\\u 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>\';  

SO网友:Trouille2

因为我一直在寻找相同的职位,但只是为了得到一个职位的条款,所以我最终编辑了这个,它对我很有用。

它的作用:
它获取特定帖子的分类名称的所有术语
对于具有两个级别(例如:级别1:“国家”和级别2:“城市”)的层次分类法,它创建了一个h4,级别1后面是级别2的ul列表,这适用于所有级别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\\u):finishingLister(\'my_taxonomy\');

我并不假装它很完美,但正如我所说的,它对我很有用。

SO网友:Pierre R

我使用了@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);

SO网友:Joe Tannorella

我有这个问题,但出于这样或那样的原因,这里没有一个答案对我有用。

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

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;

SO网友:Ariane

此解决方案的效率低于@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\' ]);

SO网友:Chip Bennett

确保hierarchical=true 已传递给您的get_terms() 呼叫

请注意hierarchical=true 是默认值,所以实际上,只需确保它没有被覆盖为false.

SO网友:Powiększanie biustu

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

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

结束

相关推荐

如何在wp_list_ategory父链接中添加类

如何在wp\\u list\\u类别中添加类,我知道wp\\u list\\u类别(\'title\\u li=\');生成类,但我想在父类别链接中添加一个类<ul> <li><a href=\"#\"> link1</a> </li> <li><a href=\"#\">link2 </a> </li> <li><a href=\"#\">