Проверить, находится ли запись в любой дочерней категории родительской категории

21 июл. 2014 г., 22:48:13
Просмотры: 16.6K
Голосов: 11

На сайте, который я разрабатываю, есть следующая структура категорий:

* movies (родительская)
    * thriller (дочерняя)
    * comedy (дочерняя)
    * drama (дочерняя)

Текущая запись находится в категории comedy. Функция has_term со следующими параметрами возвращает true:

has_term( 'comedy', 'category' )

Но та же функция со следующими параметрами возвращает false:

has_term( 'movies', 'category' )

Мой вопрос: есть ли в WordPress стандартная функция для проверки, находится ли текущая запись в любой дочерней категории указанной родительской категории? Если нет, как это можно проверить?

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

0
Все ответы на вопрос 3
1
19

Добавьте следующий код в файл functions.php вашей темы:

/**
 * Проверяет, является ли любая из категорий поста дочерней по отношению к целевым категориям
 *
 * @param int|array $cats Целевые категории. ID в виде числа или массив ID
 * @param int|object $_post Пост. Если не указан, проверяется текущий пост в цикле или основном запросе
 * @return bool Возвращает true, если хотя бы одна категория поста является дочерней для любой из целевых категорий
 * @see get_term_by() Можно получить категорию по имени или слагу, затем передать ID в эту функцию
 * @uses get_term_children() Принимает $cats
 * @uses in_category() Принимает $_post (может быть пустым)
 * @version 2.7
 * @link http://codex.wordpress.org/Function_Reference/in_category#Testing_if_a_post_is_in_a_descendant_category
 */
if ( ! function_exists( 'post_is_in_descendant_category' ) ) {
    function post_is_in_descendant_category( $cats, $_post = null ) {
        foreach ( (array) $cats as $cat ) {
            // get_term_children() принимает только числовой ID
            $descendants = get_term_children( (int) $cat, 'category' );
            if ( $descendants && in_category( $descendants, $_post ) )
                return true;
        }
        return false;
    }
}

Используйте функцию для проверки ID родительской категории, а не имени или слага. Например, если ID категории 'movies' равен 50:

if ( post_is_in_descendant_category( 50 ) ) {
    // сделать что-то
}

Если вы не знаете ID категории 'movies', вы можете получить его с помощью get_term_by() и передать в post_is_in_descendant_category():

$category_to_check = get_term_by( 'name', 'movies', 'category' );

if ( post_is_in_descendant_category( $category_to_check->term_id ) ) {
    // сделать что-то
}
21 июл. 2014 г. 23:44:10
Комментарии

Спасибо. Это должна быть встроенная функция WordPress.

David Rhoden David Rhoden
6 сент. 2020 г. 22:07:17
3

Если вам нужна любая глубина вложенности, используйте get_posts.

/**
 * Проверяет, находится ли запись в одной из категорий или любой дочерней категории.
 * 
 * @param  int|string|array $category_ids (ID одной категории) или (строка с ID, разделенными запятыми, или массив ID категорий).
 * @param  int              $post_id      ID записи для проверки. По умолчанию используется `get_the_ID()`.
 * @return bool true, если запись находится в любой категории или дочерней категории.
 */
function is_post_in_category( $category_ids, $post_id = null ) {
    $args = array(
        'include'  => $post_id ?? get_the_ID(),
        'category' => $category_ids,
        'fields'   => 'ids',
    );
    return 0 < count( get_posts( $args ) );
}

Эту функцию можно расширить разными способами. Например, передавать массив ID записей и фильтровать их или позволять уточнять запрос.

22 сент. 2020 г. 11:51:23
Комментарии

лучший ответ, так как проверяет на любой глубине.

JJS JJS
9 окт. 2021 г. 23:55:48

это кажется избыточным

DrLightman DrLightman
13 окт. 2022 г. 12:13:21

Хотя это может показаться избыточным, я думаю, это может привести к меньшему количеству SQL-запросов по сравнению с другим ответом

Matt Browne Matt Browne
13 сент. 2024 г. 03:51:19
0

Обновление для использования пользовательских таксономий:

/**
 * Проверяет, являются ли какие-либо категории поста дочерними для целевых категорий
 *
 * @param int|array $cats Целевые категории. ID в виде числа или массив ID
 * @param int|object $_post Пост. Если не указан, проверяется текущий пост в цикле или основном запросе
 * @param string $target_cat Название таксономии для запроса. Если не указано, используется стандартная таксономия 'category' для постов
 * @return bool Возвращает true, если хотя бы одна из категорий поста является дочерней для любой из целевых категорий
 * @see get_term_by() Можно получить категорию по имени или слагу, затем передать ID в эту функцию
 * @uses get_term_children() Передает $cats
 * @uses in_category() Передает $_post (может быть пустым)
 * @version 2.7
 * @link https://developer.wordpress.org/reference/functions/in_category/#comment-4999
 */
if(!function_exists('post_is_in_descendant_category')) {
  function post_is_in_descendant_category($cats, $_post = null, $target_cat = 'category') {
    foreach((array) $cats as $cat) {
      // get_term_children() принимает только числовой ID
      $descendants = get_term_children((int) $cat, $target_cat);
      if($descendants && has_term($descendants, $target_cat, $_post)) {
        return true;
      }
    }
    return false;
  }
}

Немного контекста

in_category использует has_category, который в свою очередь вызывает has_term( $category, 'category', $post ) с жестко заданной таксономией 'category'.

Использование has_term() напрямую позволяет нам проверять пользовательские таксономии, такие как product_cat (WooCommerce) или любые другие таксономии.

Функция использует category по умолчанию, поэтому может использоваться как прямая замена.

Использование

Вызовите функцию следующим образом:

if(post_is_in_descendant_category($category_to_check->term_id, $post, 'product_cat')) {
  // выполнить какое-то действие
}
15 нояб. 2022 г. 13:01:28