自定义分类,Get_the_Terms,按父项>子项的顺序列出

时间:2011-12-25 作者:turbonerd

我有一个分层自定义分类法,可以使用print_r(get_the_terms( $post->ID, \'taxonomic_rank\' ));:

Array
(
    [46] => stdClass Object
        (
            [term_id] => 46
            [name] => Aplocheilidae
            [slug] => aplocheilidae
            [term_group] => 0
            [term_taxonomy_id] => 53
            [taxonomy] => taxonomic_ranks
            [description] => 
            [parent] => 39
            [count] => 1
            [object_id] => 443
        )

    [47] => stdClass Object
        (
            [term_id] => 47
            [name] => Aplocheilus
            [slug] => aplocheilus
            [term_group] => 0
            [term_taxonomy_id] => 54
            [taxonomy] => taxonomic_ranks
            [description] => 
            [parent] => 46
            [count] => 1
            [object_id] => 443
        )

    [39] => stdClass Object
        (
            [term_id] => 39
            [name] => Cyprinodontiformes
            [slug] => cyprinodontiformes
            [term_group] => 0
            [term_taxonomy_id] => 52
            [taxonomy] => taxonomic_ranks
            [description] => 
            [parent] => 0
            [count] => 1
            [object_id] => 443
        )

)
这种分类法将始终采用以下形式:Order (家长)>Family (订单的子项)>Sub-family (家庭子女)

是否有一种快速简便的方法可以按正确的顺序显示这些分类法,以便我可以打印出以下行?Order: <order>, Family: <family>, Sub-family: <sub-family>

提前感谢

7 个回复
最合适的回答,由SO网友:Michal Mau 整理而成

也许有更好的方法可以做到这一点,但你总是可以做三个简单的foreach 循环。

我编写了一个示例函数,它很好地完成了这项工作,应该作为一个很好的起点:

function print_taxonomic_ranks( $terms = \'\' ){

    // check input
    if ( empty( $terms ) || is_wp_error( $terms ) || ! is_array( $terms ) )
        return;

    // set id variables to 0 for easy check 
    $order_id = $family_id = $subfamily_id = 0;

    // get order
    foreach ( $terms as $term ) {
        if ( $order_id || $term->parent )
            continue;
        $order_id  = $term->term_id;
        $order     = $term->name;
    }

    // get family
    foreach ( $terms as $term ) { 
        if ( $family_id || $order_id != $term->parent )
            continue;
        $family_id = $term->term_id;
        $family    = $term->name;
    }

    // get subfamily
    foreach ( $terms as $term ) { 
        if ( $subfamily_id || $family_id != $term->parent ) 
            continue;
        $subfamily_id = $term->term_id;
        $subfamily    = $term->name;
    }

    // output
    echo "Order: $order, Family: $family, Sub-family: $subfamily";

}
让它活在你的functions.php 文件并在模板中使用,如下所示:

print_taxonomy_ranks( get_the_terms( $post->ID, \'taxonomic_rank\' ) );
注意:将同一数组循环三次听起来有点愚蠢,但另一方面,这是一个快速简单的解决方案,易于阅读、扩展和维护

SO网友:Hameedullah Khan

虽然Maugly的方法看起来更具可读性,但在数组上运行3次循环对我来说并不合适。所以这里是另一种方法,它可能对某些人来说可读性较差,但在不运行循环3次的情况下也可以工作。

function print_taxonomy_ranks( $terms ) {
    // if terms is not array or its empty don\'t proceed
    if ( ! is_array( $terms ) || empty( $terms ) ) {
        return false;
    }

    foreach ( $terms as $term ) {
        // if the term have a parent, set the child term as attribute in parent term
        if ( $term->parent != 0 )  {
            $terms[$term->parent]->child = $term;   
        } else {
            // record the parent term
            $parent = $term;
        }
    }

    echo "Order: $parent->name, Family: {$parent->child->name}, Sub-Family: {$parent->child->child->name}";
}

SO网友:Kaitlyn McDonald

我遇到过这样的情况,一篇文章可以标记为多个类别组,以及父类别中的多个子类别,因此我希望我的层次结构能够反映这一点。我还想要几行代码:

$terms = get_the_terms($id, \'department_categories\');
foreach($terms as $key => $term){
    if($term->parent != 0){
        $terms[$term->parent]->children[] = $term;
        unset($terms[$key]);
    }
}
基本上,在找到类别的父对象后,它会将其作为子对象移动到父对象,然后将其从数组中的原始位置移除。我已经使用多个兄弟姐妹、孩子和不同级别的类别对此进行了测试。

希望其他人觉得这很有用,以防他们只是在寻找一些逻辑指导,而不是“插件”!

SO网友:Jonathan de Jong

这个话题有点老了,但我认为仍然相关,因为它仍然是一个完全痛苦的话题。

我使用这个递归函数,它接受两个数组作为引用。它将创建一个结构如下的数组:[term_id] => term_object->children->child_terms_array->children->child_terms_array.

<?php
function sort_terms_hierarchically( array &$terms, array &$into, $parent_id = 0 ) {
    foreach ( $terms as $i => $term ) {
        if ( $term->parent == $parent_id ) {
            $into[$term->term_id] = $term;
            unset( $terms[ $i ] );
        }
    }

    foreach ( $into as $top_term ) {
        $top_term->children = array();
        $this->sort_terms_hierarchically( $terms, $top_term->children, $top_term->term_id );
    }

}

$terms = get_the_terms( \'taxslug\', $post );
$sorted_terms = array();
sort_terms_hierarchically( $terms, $sorted_terms );

// Will log the nested arrays of term objects.
error_log( print_r( $sorted_terms, true ) );
这是我找到的唯一一个维护术语对象并处理任意数量嵌套的解决方案。

SO网友:nicogaldo

灵感来自Michal Mau answerManny Fleurmond answer 这是我的解决方案:我和@Lucas Bustamante有同样的问题:如果帖子有两个父类别呢?

我的解决方案是创建另一个对象数组,比较term_id 并检查parent 钥匙

function print_taxonomic_ranks( $terms ){

    if ( ! is_array( $terms ) || empty( $terms ) ) {
        return false;
    }

    $parent_terms = array();

    // get only parents
    foreach ( $terms as $term ) {
        if ($term->parent === 0) {
            $term->child = Array();
            $parent_terms[] = $term;
        }
    }

    // compare and nested
    foreach ( $terms as $term ) {
        if ($term->parent != 0) {
            foreach ($parent_terms as $key => $value) {
                if ($term->parent === $value->term_id) {
                    $parent_terms[$key]->child[] = $term;
                }
            }
        }
    }

    // output results
    foreach ( $parent_terms as $term ) {

        //parent term
        echo \'<span class="d-block">\'.$term->name.\'\';

        if ($term->child) {
            $i = 1;
            foreach ( $term->child as $child ) {
                //echo \'<span class="text-danger">\'.$i.\'</span>\';
                echo ($i <= 1)? ": " : "";
                echo \'<span class="font-weight-normal">\'.$child->name.\'</span>\';
                echo ($i < count($term->child))? ", " : "";
            $i++;                
            }          
        }
        echo \'.<span>\';
    }
}
它看起来像这样:

get terms in parent order

干杯

SO网友:Adam Forst

谢谢Maugly,

这是我修改过的代码版本,如果有人需要,它包含了术语permalinks

function print_show_location( $terms = \'\' ){

// check input
if ( empty( $terms ) || is_wp_error( $terms ) || ! is_array( $terms ) )
    return;

// set id variables to 0 for easy check 
$country_id = $state_id = $city_id = 0;

// get country
foreach ( $terms as $term ) {
    if ( $country_id || $term->parent )
        continue;
    $country_id  = $term->term_id;
    $country_slug = $term->slug;
    $country = \'<a href="\'.get_term_link($country_slug, \'location\').\'">\'.$term->name.\'</a>\';
}

// get state
foreach ( $terms as $term ) { 
    if ( $state_id || $country_id != $term->parent )
        continue;
    $state_id = $term->term_id;
    $state_slug = $term->slug;
    $state = \'<a href="\'.get_term_link($state_slug, \'location\').\'">\'.$term->name.\'</a>\';
}

// get city
foreach ( $terms as $term ) { 
    if ( $city_id || $state_id != $term->parent ) 
        continue;
    $city_id = $term->term_id;
    $city_slug = $term->slug;
    $city = \'<a href="\'.get_term_link($city_slug, \'location\').\'">\'.$term->name.\'</a>\';
}

// output
echo "$city, $state - $country";

}

SO网友:Luca Reghellin

根据需要,我使用了几个递归函数。两者都需要术语列表、起始父id和起始(通常为空)数组来放置结果列表。

第一版

$terms = [a list of terms objects, use get_terms of whatever]
$ordered_terms = array(); // here you\'ll find your ordered terms, from root to final child

function list_terms_by_parent($parent_id = 0, &$terms, &$ordered_terms){
  $root_parent = $parent_id;

  foreach($terms as $index => $term){
    if($term->parent == (int) $parent_id){
      $ordered_terms[$term->term_id] = $term;
      $root_parent = $term->term_id;
      unset($terms[$index]);
    }
  }

  if(!empty($terms)) list_terms_by_parent($root_parent, $terms, $ordered_terms);
}
第二版

$term_ids = [should be a list of ids in the form of child_id => parent_id]

// a fast way to get that kind of list is to use WP_Term_query, example:
//$terms_query = new WP_Term_Query(array(
//  \'taxonomy\' => \'product_categories\'
//  ,\'object_ids\' => $post->ID
//  ,\'hide_empty\' => false
//  ,\'fields\' => \'id=>parent\'
//));


$ordered_terms = array(); // here you\'ll find your ordered terms, from root to final child

function list_term_ids_by_parent($parent_id = 0, &$term_ids, &$ordered_terms){
  $child_id = array_search($parent_id, $term_ids);

  if($child_id){
    $ordered_terms[] = $child_id;
    unset($term_ids[$child_id]);
  }

  if(!empty($term_ids)) order_terms($child_id, $term_ids, $ordered_terms);
}
第三版

这不是我的,我在某处找到的,可能是在这里或stackoverflow。这在输出上有点不同,因为它将生成一个级联术语列表,只有一个根,它有一个children属性,它将包含下一个术语及其children属性,依此类推。。

//$ordered\\u terms应该是如上所述的空数组

function sort_terms_hierarchically(&$terms, &$ordered_terms, $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);
  }
}

结束

相关推荐