Вывод дочерних категорий в WordPress.

Недавно я писал, как можно вывести список подкатегорий одной из категорий в WP. Увы, сегодня обнаружил один косяк в этом алгоритме, из-за которого пришлось перекраивать функцию.
Предположим, у нас есть следующая структура категорий:

Родительская категория 1
-подкатегория 1.1
--подкатегория 1.1.1
--подкатегория 1.1.2
-подкатегория 1.2
--подкатегория 1.2.1
--подкатегория 1.2.1
-подкатегория 1.3
Родительская категория 2
-подкатегория 2.1
--подкатегория 2.1.1
Родительская категория 3
-подкатегория 3.1
--подкатегория 3.1.1

Так вот, если я захочу вывести все дочерние категории “Родительской категории 1” вот этим кодом, то я увижу следующее:

-подкатегория 1.1
--подкатегория 1.1.1
--подкатегория 1.1.2
-подкатегория 1.2
--подкатегория 1.2.1
--подкатегория 1.2.1
-подкатегория 1.3

потому как 1.1.2 является дочерней по отношению к родительской категории 1. Честно говоря, для меня это было неожиданностью, потому как в моём понимании это “внучатые” подкатегории и видеть я их в этом списке совершенно не хотел.
Кодекс мне на сей раз ничем не помог, пришлось крутить массив с индексами категорий и отсеивать ненужное.
В итоге, я получил следующий код:

// формирование сортированного массива с названиями подкатегорий
function mc_subcats ($parent_cat) {
	$parent_id = get_cat_id($parent_cat); //получаем id родительской категории
	$all_cats_ids = get_all_category_ids(); //получаем id ВСЕХ категорий
	sort( $all_cats_ids);
	foreach ( $all_cats_ids as $cat_id ) {
		$temp = true;
		if (cat_is_ancestor_of($parent_id, $cat_id)) {  //проверяем, является ли категория с cat_id дочерней по отношению к $parent_id
 			$child_cats_temp[] = $cat_id; //если дочерняя, то добавляем id  во временный массив 
 			foreach ( $child_cats_temp as $parent_temp ) { //перебираем поэлементно временный массив
 				if (cat_is_ancestor_of($parent_temp, $cat_id)) {
 					$temp = false; //если категория с cat_id является дочерней по отношению к хотя бы одному из элементов временного массива, ставим переключатель в положение ложь
 				}
 			}
 			if ($temp) {
 				$child_cats[] = get_cat_name($cat_id);
 			}
 		}
	}
	sort( $child_cats ); 
	return $child_cats; //возвращаем сортированный массив названий подкатегорий
}

Т.е. “внучатые” подкатегории отсеиваются методом двойного перебора. Теперь этот код возвращает массив со следующими названиями подкатегорий:

-подкатегория 1.1
-подкатегория 1.2
-подкатегория 1.3

Более элегантного решения этой задачи я не нашёл.

Запись опубликована в рубрике HOWTO с метками , , . Добавьте в закладки постоянную ссылку.

32 комментария на «Вывод дочерних категорий в WordPress.»

  1. Накукрыскин говорит:

    O_О
    ОМГ!!!!!!!!!!!
    Виджеты – Рубрики – “Отображать иерархию” О_О

  2. Dandr говорит:

    Накукрыскин, во-первых, я нигде не говорил про виджеты. Я ими банально не буду пользоваться;
    во-вторых, эти подкатегории мне нужне не для отображения в сайдбаре;
    в-третьих, как я уже писал ранее, мне нужен не html-список подкатегорий, а массив с их названиями или id для дальнейшей обработки.

  3. Накукрыскин говорит:

    пыщь -_- сплю. хто здесь?)))))

  4. Dandr говорит:

    Накукрыскин, а я тебе говорил – иди спать)))

  5. gonzogames.ru говорит:

    Подскажите, пожалуйста, как изменить ваш код, чтобы решить следующую задачу.

    допустим, мы находимся в посте, который относится к категориям:
    1.
    1.1
    1.1.1

    то есть к примеру сообщение про яблоню относится к категориям
    деревья
    лиственные
    яблони

    как можно извлечь id самой внучатой категории, то есть в нашем случае 1.1.1

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

    на странице сообщения о грушах – про остальные груши и тд.

    заранее спасибо.

  6. Dandr говорит:

    @ gonzogames.ru:
    так вот сразу и не скажу… Надо кодекс пошерстить…

  7. Чувствую, что это практически то, что я так долго искал!!!! Автор, очень нужна ваша помощь. Вопрос состоит в следующем:

    как сделать на странице категории вывод всех постов из каждой подкатегорий данной категории:

    Страница с категорией 1:
    –подкатегория 1.1
    —-post 1 подкатегории 1.1, в который входит title подкатегории 1.1
    —-post 2 подкатегории 1.1, в который входит title подкатегории 1.1

    –подкатегория 1.2
    —-post 1 подкатегории 1.2, в который входит title и the_content подкатегории 1.2
    ….. и т.д.

    Тема на форуме здесь: http://mywordpress.ru/support/viewtopic.php?pid=70370#p70370

    Некоторые прикидки по решению вопроса уже там изложил, туда же скопировал ваше решение, не сердитесь, пожалуйста. Вместе с вашими наработками точно все получится, но очень нужно довести до конечного итога! Пожалуйста, если найдете время, посмотрите. Большое спасибо!

  8. Dandr говорит:

    Перспективный блоггер :

    Автор, очень нужна ваша помощь.

    Сомневаюсь, что смогу помочь. Что-то я подзабросил свои начинания и из башки всё очень быстро выветрилось. Да и лето на носу, не до того)))
    В общих чертах:
    определяем текущую категорию;
    создаём массив подкатегорий (по моему коду?);
    проверяем количество подкатегорий и зацикливаем по количеству оных;
    в теле цекла перебираем подкатегории из массива и делаем запрос по аналогии со стандартным выводом постов, но для каждой подкатегории.
    Собственно, всё. 🙂

  9. Dandr говорит:

    ЗЫ за ссылочку спасибо: лишней не будет))

  10. На здоровье. Ю.Б. там уже и решение предложил ) Так что все в шоколаде )

  11. Dandr говорит:

    Перспективный блоггер :

    Так что все в шоколаде )

    Вот и чудно))

  12. Поторопился с выводами. В итоге твой кусок кода сейчас для меня оказался самым полезным, вот только хоть убей не удается вернуть из функции $child_cats, хотя в функции и есть return $child_cats;, но почему-то не работает.

    Если дописать внутри функции echo count($child_cats), а затем вызвать функцию в произвольном месте – то работает (выводит 3 – столько дочерних категорий у той, которую я передал аргументом функции), если же написать echo count($child_cats) за пределами функции, то не работает (отдает 0 вместо 3)!!!! Замучался уже. Не подскажешь, как таки правильно вернуть массив из этой функции? Мануалы гуглил, php5 читал – не просветило…

  13. Dandr говорит:

    @ Перспективный блоггер:
    :mrgreen:
    Переменные PHP.

  14. Говорю ж, мануалы читал… Мне бы только как массив вернуть из функции.

  15. Все, допер! Надо было так $my_var = mc_subcats(8); echo count($child_cats);

    Спасибо! Ссылочка пригодилась 🙂 .

  16. jump говорит:

    Не подскажите, нужно чтоб в верхнем меню сайта были родительские страницы а в сайдбаре отображались подстраницы в зависимости от выбранной странице из верхнего меню?

  17. Дмитрий говорит:

    У меня в WP при заходе в категории не отображаются подкатегории. А родительская категория вообще исчезает. Подскажите плиз как сделать. Тема не совсем стандартная. category.php нету

  18. Николай говорит:

    У меня такая проблема.
    Есть категории и подкатегории.
    Есть вертикальное меню для них.
    Если из меню открываю какую-то категорию, то выводятся посты и из подкатегорий.
    А мне надо, чтобы из подкатегорий не выводилось. Из них надо выводить когда открываю из подменю.

  19. Dandr говорит:

    @ Николай, разобрался?
    В код вникать не хочу – немного не до того. В твоём случае достаточно перед выводом сделать проверку на родительскую категорию. Если её нет, то запись выводится. Как-то так.

  20. Николай говорит:

    @ Dandr:
    Сделал так:

    $rt = get_the_category();
    if ($wp_query->queried_object->parent == 0 && $wp_query->queried_object->cat_ID != ’22’) {
    if ($wp_query->queried_object->cat_ID != $rt[0]->cat_ID) {
    $all_cats_ids = get_all_category_ids();
    $narray = (array_filter($all_cats_ids, “nopar”));
    foreach ($narray as &$tmp) { $noarray .= “,-$tmp”; }
    query_posts(‘cat=’.$wp_query->queried_object->cat_ID.’,-‘.$rt[0]->cat_ID.”.$noarray);
    }

    }
    function nopar($var) {
    global $rt;
    return ($var != $rt[0]->parent);
    }

  21. md говорит:

    Спасибо огромное 🙂 Как раз то, над чем думал несколько дней, но так и не смог придумать. Спасибо еще раз 😀

  22. Dandr говорит:

    Хм… Оказывается, тема актуальна… 😀

  23. Boroda говорит:

    Есть рубрики, в низ записи как на основе записей из рубрик построить выпадающее горизонтальное меню?

  24. Dandr говорит:

    @ Boroda,чо-то я нифига не понял…

  25. Boroda говорит:

    Dandr :

    @ Boroda,чо-то я нифига не понял…

    Есть рубрики в которых находяться записи. На основе рубрик создается корневое меню, в качестве подменю должны выступать записи из рубрики.

  26. Boroda говорит:

    @ Dandr:
    Версия WordPress 2.8.6

  27. Dandr говорит:

    @ Boroda, думаю, можно, но ковыряться лень и некогда)

  28. Boroda говорит:

    Спасибо уже сделал.

  29. Eugene Che говорит:

    Вообщем вот вам быстрая нативная рабочая функа.

    // смотрим ID текущей категории
    $id = get_category(get_query_var('cat'))->cat_ID;
    // берем все подкатегории с внуками в которых есть записи
    $cats = get_categories(array('child_of'=>$id));
    foreach($cats as $k=>$v) {
    // выводим только детей без внуков
    if ($v->parent == $id) {
    echo 'cat_ID).'">'.$v->name.'';
    }
    }

    вуаля.

  30. Сосновоборск говорит:

    чо то не получается дочерние страницы вывести в боковом меню, одни родительские показывает

  31. Dandr говорит:

    я писал это 6 лет назад… Уже как-то забил))

Добавить комментарий для DandrОтменить ответ