Получение родительского термина верхнего уровня для произвольной таксономии
Как получить родительский термин верхнего уровня для заданного термина?
Я использую wp_get_object_terms
для получения терминов таксономии для записей, но вместо отображения всех отмеченных терминов, я хочу показывать только родительские термины верхнего уровня.
Если это мои выбранные термины, я хочу показывать только Завтрак, Обед и Ужин.
x ЗАВТРАК
x Хлопья
x Яйца
ОБЕД
Гамбургер
x Пицца
УЖИН
Рыба
Окунь
x Лосось
Форель
Лазанья
Как я могу это сделать?

Спасибо Ivaylo за этот код, который основан на ответе Bainternet.
Первая функция ниже, get_term_top_most_parent
, принимает термин и таксономию и возвращает самого верхнего родителя термина (или сам термин, если у него нет родителя); вторая функция (get_top_parents
) работает в цикле и, учитывая таксономию, возвращает HTML-список самых верхних родителей терминов записи.
// Определение самого верхнего родителя термина
function get_term_top_most_parent( $term, $taxonomy ) {
// Начинаем с текущего термина
$parent = get_term( $term, $taxonomy );
// Поднимаемся по иерархии, пока не достигнем термина с parent = '0'
while ( $parent->parent != '0' ) {
$term_id = $parent->parent;
$parent = get_term( $term_id, $taxonomy);
}
return $parent;
}
Как только у вас есть функция выше, вы можете перебирать результаты, возвращенные wp_get_object_terms
, и отображать самого верхнего родителя каждого термина:
function get_top_parents( $taxonomy ) {
// Получаем термины для текущей записи
$terms = wp_get_object_terms( get_the_ID(), $taxonomy );
$top_parent_terms = array();
foreach ( $terms as $term ) {
// Получаем самого верхнего родителя
$top_parent = get_term_top_most_parent( $term, $taxonomy );
// Проверяем, есть ли он уже в массиве, чтобы добавить только один раз
if ( !in_array( $top_parent, $top_parent_terms ) ) {
$top_parent_terms[] = $top_parent;
}
}
// Формируем вывод (HTML на ваше усмотрение)
$output = '<ul>';
foreach ( $top_parent_terms as $term ) {
// Добавляем каждый термин
$output .= '<li><a href="'. get_term_link( $term ) . '">' . $term->name . '</a></li>';
}
$output .= '</ul>';
return $output;
}

Мне бы хотелось увидеть модификацию, которая выводила бы не только термины верхнего уровня, а все термины ниже самого верхнего родителя, в иерархическом порядке.

@RobertAndrews Если вам нужны только дочерние элементы одного термина, вы можете использовать встроенную функцию WordPress get_term_children( $term, $taxonomy )
(документация).
Если вы хотите получить все дочерние элементы самого верхнего родителя данного термина, вы можете передать результат выше в эту функцию, вот так: get_term_children( get_term_top_most_parent( $term, $taxonomy ), $taxonomy )
.

Что представляет собой $term в данном случае - объект, название термина, имя таксономии с префиксом_number? В любом случае, этот метод очень долго грузится. Я жду загрузки страницы уже несколько минут.

Изначально код ожидал ID, но я отредактировал ответ, чтобы он мог принимать как ID термина, так и объект WP_Term.
Вы не единственный, кто сообщает о проблеме с этим кодом — в идеале его следует переписать с использованием встроенной функции WP get_ancestors
, которая была новой и плохо документирована на момент написания ответа. Я опубликую новый ответ, когда у меня будет время протестировать.

Начиная с версии 3.1.0, доступна функция get_ancestors()
. Она возвращает массив предков (родительских элементов) в порядке от низшего к высшему в иерархии.

Вот простая функция, которая позволит получить самый верхний родительский элемент для любого заданного термина:
function get_term_top_most_parent( $term_id, $taxonomy ) {
$parent = get_term_by( 'id', $term_id, $taxonomy );
while ( $parent->parent != 0 ){
$parent = get_term_by( 'id', $parent->parent, $taxonomy );
}
return $parent;
}
После создания этой функции вы можете просто перебрать результаты, возвращаемые функцией wp_get_object_terms
:
$terms = wp_get_object_terms( $post->ID, 'taxonomy' );
$top_parent_terms = array();
foreach ( $terms as $term ) {
//Получаем самый верхний родительский элемент
$top_parent = get_term_top_most_parent( $term->ID, 'taxomony' );
//Проверяем, есть ли он уже в массиве, чтобы добавить только один раз
if ( !in_array( $top_parent->ID, $top_parent_terms ) ) {
$top_parent_terms[] = $top_parent;
}
}

Спасибо! Пробую это сейчас. Кстати, кажется, у вас не хватает закрывающей скобки в первой строке функции.

Я добавил параметр $taxonomy, но получаю ошибку при использовании этого кода, вот здесь: https://gist.github.com/1122631

Теперь, когда это исправлено, ты не знаешь, почему код здесь (http://gist.github.com/1122631) не работает?

твоя функция кажется сломанной, твои циклы foreach перекрываются, попробуй это: http://pastebin.com/u48dxzap и если ошибка останется, вставь весь свой код, и я проверю

Ошибка всё та же; если сделать print_r($top_parent_terms), получается пустой массив, так что, возможно, проблема в первой функции? Моя версия здесь - http://pastebin.com/cMUxs9Nn

Ладно, думаю, проблема в get_the_ID
, который работает внутри цикла, так что попробуйте это: http://pastebin.com/u48dxzap

@Bainternet давайте продолжим обсуждение в чате

@Bainternet - это сообщение в чате было опубликовано автоматически? Что касается global $post и post->ID, я использую это внутри циклов WP_Query, поэтому get_the_ID должен работать.

У меня была такая же проблема, и я легко её решил. Вот как:
Определите $taxonomy
. Это может быть ярлык таксономии, данные которой вы хотите получить.
После этого вы можете просто сделать следующее:
<?php
$postterms = wp_get_post_terms($post->ID, $taxonomy); // получаем термины поста
$parentId = $postterms[0]->parent; // получаем ID родительского термина
$parentObj = get_term_by('id', $parentId, $taxonomy); // получаем объект родителя
?>
Теперь у вас будет что-то вроде этого:
object(stdClass)#98 (11) {
["term_id"]=>
int(3)
["name"]=>
string(8) "Спорт"
["slug"]=>
string(8) "sport"
["term_group"]=>
int(0)
["term_taxonomy_id"]=>
int(3)
["taxonomy"]=>
string(17) "noticiaseditorias"
["description"]=>
string(0) ""
["parent"]=>
int(0)
["count"]=>
int(4)
["object_id"]=>
int(123)
["filter"]=>
string(3) "raw"
}
И вы можете использовать $parentObj
для получения ярлыка, названия, ID или чего угодно. Просто используйте $parentObj->slug
или $parentObj->name
в качестве примера.

Возможно, это поможет: get_ancestors( $object_id, $object_type );
