Verificar si un post pertenece a cualquier categoría hija de una categoría padre
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

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
}

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.

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
}
