Comprobar si se está mostrando una página de archivo de taxonomía personalizada
Tengo un tipo de entrada personalizada llamado 'advert' y una taxonomía personalizada relacionada llamada 'advert_category', creados por un plugin de terceros. Ejecuto en un plugin una declaración if
que debe establecer (como espero) un diseño de tema específico para anuncios individuales (example.com/advert/un-anuncio-individual.html) y para páginas de archivo de taxonomía personalizada (example.com/advert-category/servicios/), pero la segunda condición is_tax( 'advert_category' )
no funciona. ¿Qué está mal aquí?
Mi código:
function my_advert_single_template( ) {
global $post;
global $wpgo_global_column_layout;
if ( $post->post_type == 'advert' || is_tax( 'advert_category' ) ) {
$wpgo_global_column_layout = "2-col-l";
}
}
add_filter( 'single_template', 'my_advert_single_template' );
Así es como están registrados el tipo de entrada personalizada y la taxonomía personalizada:
// registrar tipo de entrada y taxonomía para permitir la inserción de datos predeterminados
register_post_type( 'advert' );
register_taxonomy( 'advert_category', 'advert' );
$hid = wp_insert_post(array(
'post_type' => 'page',
'post_status' => 'publish',
'post_title' => 'Adverts',
'comment_status' => 'closed',
'ping_status' => 'closed',
'post_content' => "[adverts_list]"
));
$aid = wp_insert_post(array(
'post_type' => 'page',
'post_status' => 'publish',
'post_title' => 'Add',
'post_parent' => $hid,
'comment_status' => 'closed',
'ping_status' => 'closed',
'post_content' => "[adverts_add]"
));
$mid = wp_insert_post(array(
'post_type' => 'page',
'post_status' => 'publish',
'post_title' => 'Manage',
'post_parent' => $hid,
'comment_status' => 'closed',
'ping_status' => 'closed',
'post_content' => "[adverts_manage]"
));
wp_insert_term(
'Default',
'advert_category'
);
Tienes muchos problemas aquí:
pre_get_posts
no es el hook correcto para establecer plantillas.pre_get_posts
se usa para alterar las variables de consulta justo antes de que se construya el SQL para ejecutar la consulta principal.Un filtro debe siempre devolver algo. No hacer esto puede causar comportamientos inesperados, y olvidarse de esto puede hacerte perder horas depurando el problema.
Usar variables globales para controlar características del tema o almacenar cualquier tipo de datos es una mala práctica y no es seguro. WordPress ya tiene un gran desorden con las variables globales, especialmente en convenciones de nombres. Solo fíjate cómo los principiantes (que no conocen WordPress) usan variables como
$post
y$posts
como variables locales. Estas son variables globales nativas de WordPress, y usarlas como variables locales rompe sus valores.Debido a esto, algo en la página falla, no hay errores, y te quedas atascado intentando depurar algo que has roto sin saberlo. Las variables globales son puro mal y deberías evitarlas. Imagina que usas la variable
$wpgo_global_column_layout
para los argumentos de una consulta personalizada, romperás el valor de la plantilla que necesita establecerse. Tu plantilla no se carga porque el valor de$wpgo_global_column_layout
no se reconoce como un nombre de plantilla válido, y no sabes por qué tu plantilla no se carga aunque tu código es 100% correcto.is_tax()
es la comprobación incorrecta para ver si un post tiene un término específico.is_tax()
simplemente verifica si estás en un archivo de taxonomía. Deberías usarhas_term()
, que hace exactamente eso: comprobar si un post tiene un término específico.Si necesitas establecer una plantilla para una página de taxonomía,
single_template
es el hook incorrecto. Deberías usar el hooktaxonomy_template
o el filtro más genéricotemplate_include
.En la línea
$post->post_type == 'advert' || is_tax( 'advert_category' )
, sospecho que estás usando el operador incorrecto. Deberías usar el operadorAND
. No voy a explicar esto aquí porque ya lo hice aquí. Ten en cuenta que, con la configuración actual, cada vez que veas un post del tipoadvert
, tu condición devolverá verdadero y se ejecutará, independientemente de si la segunda condición (is_tax( 'advert_category' )
) falla o no.Si necesitas seleccionar un término según su relación padre/hijo, simplemente debes verificar la propiedad
$parent
del objeto término. Un valor de0
significa que el término es padre, cualquier otro valor significa que es hijo/nieto/bisnieto/etc.
Vamos a dejar de lado las variables globales malas y establecer las plantillas correctamente. No sé exactamente cómo tu tema establece plantillas a través de $wpgo_global_column_layout
, pero lo siguiente debería funcionar con prioridad. He comentado el código para que sea fácil de seguir.
PARA PÁGINAS INDIVIDUALES:
add_filter( 'single_template', function ( $template )
{
// Elimina todos los filtros del filtro actual
remove_all_filters( current_filter(), PHP_INT_MAX );
/**
* Obtiene el objeto del post actual. Usamos get_queried_object
* porque es más seguro que usar $post
*
* @see https://wordpress.stackexchange.com/q/167706/31545
*/
$current_post = get_queried_object();
// Verifica si el post actual pertenece al tipo 'advert', si no, salimos
if ( $current_post->post_type !== 'advert' )
return $template;
// Obtiene los términos del post
$terms = get_the_terms(
$current_post, // Objeto del post actual
'advert_category' // Nombre de la taxonomía
);
// Si $terms está vacío o devuelve un objeto WP_Error, salimos
if ( !$terms || is_wp_error( $terms ) )
return $template;
/**
* Obtiene el primer término y verifica si es de nivel superior o no.
* Carga la plantilla según el valor de parent
*
* NOTA: Esto solo funciona correctamente si el post tiene un solo término
*/
if ( $terms[0]->parent == 0 ) {
$part = 'single-parent.php'; // Establece la plantilla para términos padre
} else {
$part = 'single-child.php'; // Establece la plantilla para términos hijo
}
// Verifica si la plantilla existe, si no, salimos
$locate_template = locate_template( $part );
if ( !$locate_template )
return $template;
// Hemos llegado a este punto, establecemos nuestra plantilla personalizada
return $template = $locate_template;
}, PHP_INT_MAX + 1 );
PARA PÁGINAS DE TAXONOMÍA:
add_filter( 'taxonomy_template', function ( $template )
{
// Elimina todos los filtros del filtro actual
remove_all_filters( current_filter(), PHP_INT_MAX );
// Obtiene el objeto del término actual. Usamos get_queried_object
$current_term = get_queried_object();
// Si el término actual no pertenece a 'advert_category', salimos
if ( $current_term->taxonomy !== 'advert_category' )
return $template;
// Verifica si el término es de nivel superior o no y establece la plantilla
if ( $current_term->parent == 0 ) {
$part = 'taxonomy-parent.php'; // Plantilla para términos padre
} else {
$part = 'taxonomy-child.php'; // Plantilla para términos hijo
}
// Verifica si la plantilla existe, si no, salimos
$locate_template = locate_template( $part );
if ( !$locate_template )
return $template;
// Hemos llegado a este punto, establecemos nuestra plantilla personalizada
return $template = $locate_template;
}, PHP_INT_MAX + 1 );
Solo una nota, todo el código no ha sido probado, así que asegúrate de probarlo localmente primero con el modo de depuración activado. También modifica y adapta el código según tus necesidades.

No funciona :(. Según FunctionReference/has term: "Comprueba si la publicación actual tiene alguno de los términos dados", entonces, ¿esto solo funcionará en publicaciones individuales?

Eso funciona en páginas individuales, ¿cuál es el problema? Decir no funciona es muy vago

Me refiero a que la página 'example.com/advert-category/services/' no cambia la plantilla.

Tienes dos problemas en tu función:
- Falta un argumento en el filtro "single_template" y por lo tanto el filtro no está devolviendo lo que debería.
- También estás llamando a has_term() sin especificar la taxonomía en la que estás intentando buscar.
Revisa esto:
function my_advert_single_template( $single_template ) {
global $post;
global $wpgo_global_column_layout;
if ( $post->post_type == 'advert' || has_term( 'util-categorie', 'advert_category' ) ) {
$wpgo_global_column_layout = "2-col-l";
}
return $single_template;
}
add_filter( 'single_template', 'my_advert_single_template' );

Corregí algunos errores en mi código antiguo (era una variante de prueba, lo siento, parece que aún no estaba despierto). Y probé tu función, pero no funciona para páginas de taxonomías personalizadas, solo para publicaciones individuales. Encontré una solución (mira la actualización).
