Пользовательская таксономия, get_the_terms, перечисление в порядке родительского> ребенок

У меня есть иерархическая пользовательская таксономия, которую я могу отобразить с помощью 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: <order>, Family: <family>, Sub-family: <sub-family>

Заранее спасибо

6 голосов | спросил dunc 26 MonEurope/Moscow2011-12-26T00:21:36+04:00Europe/Moscow12bEurope/MoscowMon, 26 Dec 2011 00:21:36 +0400 2011, 00:21:36

5 ответов


7

Есть, вероятно, несколько лучших способов сделать это, но вы всегда можете сделать три простых цикла 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' ) );

ПРИМЕЧАНИЕ. Цикл одного и того же массива три раза вокруг звучит немного глупо, но, с другой стороны, это быстрое и простое решение, которое легко читать, расширять и поддерживать.

ответил Michal Mau 27 TueEurope/Moscow2011-12-27T18:19:01+04:00Europe/Moscow12bEurope/MoscowTue, 27 Dec 2011 18:19:01 +0400 2011, 18:19:01
5

Хотя подход Могли кажется немного более читаемым, но запуск цикла 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}";
}
ответил Hameedullah Khan 28 WedEurope/Moscow2011-12-28T12:58:36+04:00Europe/Moscow12bEurope/MoscowWed, 28 Dec 2011 12:58:36 +0400 2011, 12:58:36
3

У меня была ситуация, когда сообщение могло быть помечено несколькими группами категорий и несколькими дочерними элементами в родительских категориях, поэтому я хотел, чтобы моя иерархия отражала это. Я также просто хотел несколько строк кода:

$terms = get_the_terms($id, 'department_categories');
foreach($terms as $key => $term){
    if($term->parent != 0){
        $terms[$term->parent]->children[] = $term;
        unset($terms[$key]);
    }
}

В основном после того, как он находит родителя категории, он перемещает его в родительский obj в качестве дочернего элемента, а затем удаляет его из исходной позиции в массиве. Я тестировал это с использованием нескольких братьев и сестер, детей и разных уровней категорий.

Надеюсь, что кто-то найдет это полезным, если они просто ищут логическое руководство, а не «плагин»!

ответил Kaitlyn McDonald 8 J000000Monday13 2013, 18:57:46
2

Похоже на старую тему, но по-прежнему актуальной. Я думаю, что это все еще полная боль.

Я использую эту рекурсивную функцию, которая принимает в качестве массива два массива. Он создаст массив со структурой: [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 ) );

Это единственное решение, которое я когда-либо нашел, поддерживающий термин «объекты» и работающий с любым количеством вложенности.

ответил Jonathan de Jong 20 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 20 Sep 2016 15:25:54 +0300 2016, 15:25:54
1

Спасибо Могли,

Вот моя модифицированная версия вашего кода, которая включает термин 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";

}
ответил Adam Forst 25 Jam1000000amWed, 25 Jan 2012 05:10:23 +040012 2012, 05:10:23

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132