Verificar si un post pertenece a cualquier categoría hija de una categoría padre

21 jul 2014, 22:48:13
Vistas: 16.6K
Votos: 11

En un sitio que estoy desarrollando, tengo la siguiente estructura de categorías:

* películas (padre)
    * thriller (hija)
    * comedia (hija)
    * drama (hija)

El post actual está en la categoría comedia. La función has_term con los siguientes parámetros devuelve true:

has_term( 'comedia', 'category' )

Pero, la misma función con los siguientes parámetros devuelve false:

has_term( 'películas', 'category' )

Mi pregunta es, ¿existe alguna función nativa para verificar si el post actual está en cualquier categoría hija de una categoría padre específica? Si no existe, ¿cómo puedo comprobarlo?

Gracias de antemano

0
Todas las respuestas a la pregunta 3
1
19

Añade lo siguiente al archivo functions.php de tu tema:

/**
 * Comprueba si alguna de las categorías asignadas a un post es descendiente de las categorías objetivo
 *
 * @param int|array $cats Las categorías objetivo. ID entero o array de IDs enteros
 * @param int|object $_post El post. Omite para comprobar el post actual en el Loop o consulta principal
 * @return bool True si al menos 1 de las categorías del post es descendiente de cualquiera de las categorías objetivo
 * @see get_term_by() Puedes obtener una categoría por nombre o slug, luego pasa el ID a esta función
 * @uses get_term_children() Pasa $cats
 * @uses in_category() Pasa $_post (puede estar vacío)
 * @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() acepta solo ID entero
            $descendants = get_term_children( (int) $cat, 'category' );
            if ( $descendants && in_category( $descendants, $_post ) )
                return true;
        }
        return false;
    }
}

Usa la función para comprobar el ID de la categoría padre, no el nombre o slug. Ej. si el ID de la categoría 'películas' es 50:

if ( post_is_in_descendant_category( 50 ) ) {
    // hacer algo
}

Si no conoces el ID de la categoría 'películas', puedes obtener el ID usando get_term_by() y pasarlo a post_is_in_descendant_category():

$category_to_check = get_term_by( 'name', 'películas', 'category' );

if ( post_is_in_descendant_category( $category_to_check->term_id ) ) {
    // hacer algo
}
21 jul 2014 23:44:10
Comentarios

Gracias. Esto debería ser una función integrada de WordPress.

David Rhoden David Rhoden
6 sept 2020 22:07:17
3

Si deseas cualquier nivel de anidación, utiliza get_posts.

/**
 * Verifica si el post está en una de las categorías o en cualquier categoría hija.
 * 
 * @param  int|string|array $category_ids (ID de una sola categoría) o (cadena separada por comas o array de IDs de categorías).
 * @param  int              $post_id      ID del post a verificar. Por defecto usa `get_the_ID()`.
 * @return bool true, si el post está en cualquier categoría o categoría hija.
 */
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 ) );
}

Puedes expandir esta función de muchas maneras. Tal vez pasar un array de IDs de posts y filtrar algunos o permitir que la consulta sea refinada.

22 sept 2020 11:51:23
Comentarios

mejor respuesta ya que verifica cualquier profundidad.

JJS JJS
9 oct 2021 23:55:48

esto parece excesivo

DrLightman DrLightman
13 oct 2022 12:13:21

Aunque pueda parecer excesivo, creo que esto podría resultar en menos consultas SQL que la otra respuesta

Matt Browne Matt Browne
13 sept 2024 03:51:19
0

Actualización para usar taxonomías personalizadas:

/**
 * Comprueba si alguna de las categorías asignadas a una publicación es descendiente de las categorías objetivo
 *
 * @param int|array $cats Las categorías objetivo. ID entero o array de IDs enteros
 * @param int|object $_post La publicación. Omite para comprobar la publicación actual en el Loop o consulta principal
 * @param string $target_cat El nombre de la taxonomía a consultar. Omite para usar la taxonomía por defecto 'category' utilizada para publicaciones
 * @return bool Verdadero si al menos 1 de las categorías de la publicación es descendiente de cualquiera de las categorías objetivo
 * @see get_term_by() Puedes obtener una categoría por nombre o slug, luego pasar el ID a esta función
 * @uses get_term_children() Pasa $cats
 * @uses in_category() Pasa $_post (puede estar vacío)
 * @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() solo acepta ID entero
      $descendants = get_term_children((int) $cat, $target_cat);
      if($descendants && has_term($descendants, $target_cat, $_post)) {
        return true;
      }
    }
    return false;
  }
}

Algo de contexto

in_category usa has_category que a su vez llama a has_term( $category, 'category', $post ) con la taxonomía 'category' codificada de forma fija.

Usando has_term() directamente nos permite comprobar una taxonomía personalizada como product_cat (WooCommerce) o cualquier otra taxonomía.

La función usa category como valor predeterminado por lo que puede usarse como reemplazo directo.

Uso

Llama a la función así:

if(post_is_in_descendant_category($category_to_check->term_id, $post, 'product_cat')) {
  // hacer algo
}
15 nov 2022 13:01:28