根据深度显示自定义分类的层次子术语

时间:2017-03-09 作者:Traveler

特定职位有以下层次分类结构:

术语A子术语A.1子术语A.2子术语A.2.1如何显示

所有父级术语(结果:A、B)所有二级术语(结果:A.1、A.2、B.1)

  • 所有三级术语(结果:A.2.1、B.1.1、B.1.2)
    4 个回复
    SO网友:Ben Casey

    我喜欢好的挑战!

    此处的功能:

    function get_post_categories_sorted ( $post_id ){
    
        $terms = wp_get_post_terms( $post_id, \'category\' );
    
        $sorted_terms = [];
    
        foreach( $terms as $term ){
    
            $depth = count( get_ancestors( $term->term_id, \'category\' ) );
    
            if( ! array_key_exists( $depth, $sorted_terms ) ){
                $sorted_terms[$depth] = [];
            }
    
            $sorted_terms[$depth][] = $term;
    
        }
    
        return $sorted_terms;
    
    }
    
    将为您提供一个数组,其结构如下图所示。$sorted_terms[0] 包含顶级术语,$sorted_terms[1] 所有的二级术语等等。

    Sorted Terms for a given post

    使用缓存或transients API来存储数据肯定是值得的,因为它可能需要花费大量的术语来进行排序,因为get\\u祖先的调用涉及对数据库的调用,它必须遍历备份链的每个级别。

    EDIT

    您可以使用以下内容:

    $sorted_terms = get_post_categories_sorted( get_the_ID() );
    
    foreach( $sorted_terms as $key => $level_items ){
    
        $number = $key + 1;
    
        echo sprintf( \'<p>Level %s Categories</p>\', $number );
    
        echo \'<ul>\';
    
            foreach( $level_items as $term ){
                echo sprintf( \'<li>%s</li>\', $term->name );
            }
    
        echo \'</ul>\';
    
    }
    

    EDIT 2

    要仅使用特定级别,可以将上面的代码简化为:

    $sorted_terms = get_post_categories_sorted( get_the_ID() );
    
    echo \'<p>Level 1 Categories</p>\';
    
    echo \'<ul>\';
        //Change the 0 here to whatever level you need, 
        //just remember is is 0 based; IE the first level is 0, 2nd level is 1 etc.
        //If the number doesn\'t exist, PHP will throw an undefined index error.
    
        foreach( $sorted_items[0] as $term ){ 
            echo sprintf( \'<li>%s</li>\', $term->name );
        }
    
    echo \'</ul>\';
    

    SO网友:Traveler

    使用找到了最简单的解决方案get_the_terms() | Function. 我真的不知道为什么2级的数字($terms[2]) 和3($terms[1]) 顺序不正确,但至少它是通过Wordpress函数实现的。

    1级:

    <?php
    $terms = get_the_terms( $post->ID, \'custom_taxonomy\' );
    echo $terms[0]->name;
    ?>  
    
    第2级:

    <?php
    $terms = get_the_terms( $post->ID, \'custom_taxonomy\' );
    echo $terms[2]->name;
    ?>  
    
    级别3:

    <?php
    $terms = get_the_terms( $post->ID, \'custom_taxonomy\' );
    echo $terms[1]->name;
    ?>  
    

    SO网友:Traveler

    code 正在部分工作,在此示例中显示了第三级的术语\'depth\' => 3. 不幸的是,也列出了父条款,如何排除父条款?

    <?php function wpse244577_list_terms( $taxonomy, $separator = \', \' ) {        
        // Get the term IDs assigned to post.
        $post_terms = wp_get_object_terms( get_the_ID(), $taxonomy, [ \'fields\' => \'ids\' ] );
        if ( ! empty( $post_terms ) && ! is_wp_error( $post_terms ) ) {
            $terms = wp_list_categories( [
                    \'title_li\'  => \'\',
                    \'style\'     => \'none\',
                    \'echo\'      => false,
                    \'taxonomy\'  => $taxonomy,
                    \'include\'   => $post_terms,
                    \'separator\' => $separator,
                    \'depth\'  => 3,
            ] );
            $terms = rtrim( trim( str_replace( $separator, $separator, $terms ) ), \', \' );
            $terms = explode( $separator, $terms );
            $terms = array_reverse( $terms );
            $terms = implode( $separator, $terms );
            echo  $terms;
        }
    } wpse244577_list_terms( \'custom_taxonomy\' ); ?>
    

    SO网友:Willington Vega

    这里有一个替代解决方案。以下函数接受一个参数数组,其中包含两个可能的键:

    • taxonomy: 字符串。分类的名称
    • level: 一个int。0表示根元素,1表示根元素的子元素,依此类推
    它返回WP_Term 对象。

    function wpse_259499_get_subterms( $args = array() ) {
        $args = wp_parse_args( $args, array( \'taxonomy\' => \'category\', \'level\' => 0 ) );
    
        $subterms = get_transient( \'taxonomy-subterms-\' . $args[\'taxonomy\'] . \'-\' . $args[\'level\'] );
        $terms_ids = array();
    
        if ( is_array( $subterms ) ) {
            return $subterms;
        }
    
        if ( 0 == $args[\'level\'] ) {
            $terms = get_terms( array(
                \'taxonomy\' => $args[\'taxonomy\'],
                \'get\' => \'all\',
                \'orderby\' => \'id\',
                \'fields\' => \'id=>parent\',
            ) );
    
            foreach ( $terms as $term_id => $parent ) {
                if ( ! $parent ) {
                    $terms_ids[] = $term_id;
                }
            }
        } else if ( $hierarchy = _get_term_hierarchy( $args[\'taxonomy\'] ) ) {
            $subterms_args = array( \'taxonomy\' => $args[\'taxonomy\'], \'level\' => $args[\'level\'] - 1 );
    
            foreach ( wpse_259499_get_subterms( $subterms_args ) as $term ) {
                if ( isset( $hierarchy[ $term->term_id ] ) ) {
                    $terms_ids = array_merge( $terms_ids, $hierarchy[ $term->term_id ] );
                }
            }
        }
    
        if ( $terms_ids ) {
            $subterms = get_terms( array(
                \'taxonomy\' => $args[\'taxonomy\'],
                \'get\' => \'all\',
                \'include\' => $terms_ids,
            ) );
        } else {
            $subterms = array();
        }
    
        set_transient( \'taxonomy-subterms-\' . $args[\'taxonomy\'] . \'-\' . $args[\'level\'], $subterms, HOUR_IN_SECONDS );
    
        return $subterms;
    }
    
    Note 1: 如果您决定重命名该函数,请注意该函数正在调用自身,因此您还需要在递归调用中更改名称。

    Note 2: 结果将在瞬态中存储一个小时。为了在开发过程中获得新的结果,可以在函数开头添加以下行:

    delete_transient( \'taxonomy-subterms-\' . $args[\'taxonomy\'] . \'-\' . $args[\'level\'] );
    
    如果您希望始终获得准确的结果,那么您可能还需要在每次添加、删除或修改感兴趣的分类中的类别时删除这些瞬态。

    示例可以在模板中使用以下代码,以生成指向所选级别中所有术语的无序链接列表:

    <ul>
    <?php foreach ( wpse_259499_get_subterms( array( \'taxonomy\' => \'category\', \'level\' => 0 ) ) as $term ): ?>
        <li><a href="<?php echo esc_attr( get_term_link( $term ) ); ?>"><?php echo esc_html( $term->name ); ?></a></li>
    <?php endforeach; ?>
    </ul>