Как упорядочить результат get_categories
Я прочитал документацию в кодексе, но не могу упорядочить результат get_categories() так, чтобы сначала шли родительские категории, а затем дочерние.
У меня есть такая структура категорий:
-События
- Музыка
- Культура
- Мастер-классы
- Туризм
-Спорт
-Футбол
-Регби
-Теннис
Я хочу получить вывод в таком виде:
События, Музыка
Я пробовал:
echo $product->get_categories();
и результат выводится как Музыка, События (сначала дочерняя, затем родительская категория).
Я также пробовал передать $args в качестве аргумента get_categories():
$args = array(
'type' => 'post',
'child_of' => 0,
'parent' => '',
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => 1,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);
Как мне упорядочить категории так, как я хочу?
Во-первых, $product->get_categories()
не сработает, так как это функция WooCommerce, которая по сути является обёрткой для get_the_term_list
, не имеющей параметра сортировки. Всегда полезно заглянуть в исходный код, чтобы понимать, с чем имеешь дело.
Во-вторых, get_the_term_list
использует get_the_terms
, но она также не имеет параметра сортировки. Последняя получает термины либо из кэша get_object_term_cache
, либо напрямую через wp_get_object_terms
. Кэш, скорее всего, бесполезен, так как термины там сохраняются с неправильной сортировкой, что и вызывает вашу проблему. wp_get_object_terms
, с другой стороны, наконец-то позволяет задать сортировку.
Из кодекса:
Использование
wp_get_object_terms( $object_ids, $taxonomies, $args )
Аргументы по умолчанию
$args = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
Первый аргумент называется 'orderby' и имеет значение по умолчанию 'name'. Другие поддерживаемые значения: 'count', 'slug', 'term_group', 'term_order' и 'term_id'.
Второй аргумент называется 'order' и имеет значение по умолчанию 'ASC'. Единственное другое допустимое значение — 'DESC'.
Это может приблизить вас к желаемому результату, но лучше изучить вопрос самостоятельно.
В-третьих, вы можете просто использовать get_ancestors
, который возвращает
Массив предков от самого низкого до самого высокого в иерархии
Это хорошо работает с таксономией категорий товаров WooCommerce, так как она иерархическая. Однако могут возникнуть сложности, если вы назначаете несколько терминов на одном уровне иерархии. Я написал ответ по этой общей теме, возможно, он вам поможет.

Я написал этот код, который запускаю после get_categories. Он сортирует результаты по родительским категориям и именам:
$all_categories = get_categories( $args );
$byId = array();
// Создаем массив категорий по id
foreach ($all_categories as $cat) {
$byId[$cat->term_id] = $cat;
}
// Добавляем новое поле path, по которому будем сортировать
foreach ($all_categories as $cat) {
$path = $cat->name;
$parentCat = $cat;
for($n=0;$n<10 && $parentCat->parent > 0;$n++) {
// Ограничиваем 10 уровнями (можно изменить при необходимости)
$parentCat = $byId[$parentCat->parent];
$path = $parentCat->name."/".$path;
}
$cat->path = $path;
}
// Финальная сортировка по новому полю path
function cmp($a, $b) {
return strcmp($a->path,$b->path);
}
usort($all_categories, "cmp");
// Теперь $all_categories отсортированы по иерархии и имени

У меня нет такой настройки, как у вас, поэтому давайте попробуем кое-что. Я даю код, а вы лучше попробуйте и дайте мне обратную связь. Удовлетворяет ли результат?
<?php
$args = array(
'type' => 'post', // Тип записи
'child_of' => 0, // ID родительской категории
'parent' => '', // Родительская категория
'orderby' => 'name', // Сортировка по названию
'order' => 'ASC', // Порядок сортировки (по возрастанию)
'hide_empty' => false, // Показывать пустые категории
'hierarchical' => 1, // Иерархический вывод
'exclude' => '', // Исключаемые категории
'include' => '', // Включаемые категории
'number' => '', // Количество категорий
'taxonomy' => 'category', // Таксономия
'pad_counts' => false // Учитывать дочерние категории
);
$cats = get_categories( $args );
//var_dump($cat);
foreach( $cats as $cat ){
echo $cat->name .', '; // Выводим названия категорий через запятую
}
?>

Я попробовал:
<?php
$args = array(
'type' => 'product',
'child_of' => 0,
'parent' => '',
'orderby' => 'term_group',
'hide_empty' => false,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'product_cat',
'pad_counts' => false
);
$cats = get_categories( $args );
//var_dump($cat);
foreach( $cats as $cat ){
echo $cat->name.', ';
}
?>
Это выводит все категории с учетом иерархии, в моем случае:
Events, Sport, Music, Culture, Workshop, Tourism, Football, Rugby, Tennis.
Мне нужно просто исключить категории, не выбранные для записи.
