Taxonomía Personalizada y Tax_Query
He tenido muchos problemas para hacer funcionar un WP_Query
con un tax_query
en mi taxonomía personalizada.
Estoy 99.9% seguro de que mi register_taxonomy
es correcto, ya que puedo etiquetar entradas con el término correcto, verlo en la base de datos, y el término correcto se devuelve con esta función: http://pastebin.com/18Aj1ysT.
Pero cuando uso un tax_query
en mi WP_Query
, no obtengo ninguna entrada. Mi consulta es:
$nextSundayTalkArgs = array(
'post_type' => 'talk',
'posts_per_page' => 1,
'tax_query' => array(
array(
'taxonomy' => 'talktype',
'field' => 'slug',
'terms' => 'sunday-talk'
)
)
);
$nextSundayTalkQuery = new WP_Query( $nextSundayTalkArgs );
Funciona perfectamente sin 'tax_query'. Si uso algo como 'talktype' => 'sunday-talk' en su lugar, usando query_var cuando registro la taxonomía, simplemente ignora la línea como si no estuviera allí e imprime cualquier charla (en lugar de decir "no hay entradas").
Al insertar <?php echo $GLOBALS['nextSundayTalkQuery']->request; ?>
obtengo esto:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts WHERE 1=1
AND 0 = 1
AND wp_posts.post_type = 'talk'
AND (
wp_posts.post_status = 'publish'
OR wp_posts.post_author = 1
AND wp_posts.post_status = 'private'
)
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 1
Usar código idéntico para consultar la taxonomía predeterminada "category" de WordPress funciona bien, por lo que parece estar relacionado con mi taxonomía personalizada o tipo de entrada. Para ahorrar espacio en esta publicación, mi código de tipo de entrada personalizado está aquí:
y mi código de taxonomía personalizada está aquí:
He intentado incluir 'include_children' => false
como se ha sugerido, pero sin éxito.
Agradecería cualquier ayuda, ya que este problema ha sido irresoluble durante meses con muchas personas tratando (y fallando, desafortunadamente) de descubrir qué está mal.
En primer lugar, ejecutas register_post_type
en init
y register_taxonomy
en after_setup_theme
que se llama después de init
. Esto significa que tu taxonomía personalizada no estará disponible al registrar el tipo de contenido. Sugiero que elimines la palabra clave taxonomies
de la matriz de argumentos de register_post_type
, y simplemente registres la taxonomía manualmente después. En tu código de ejemplo, parece que estás creando el enlace entre el tipo de contenido y la taxonomía dos veces.
Tampoco estoy seguro acerca de 'query_var' => true,
en la matriz de argumentos de register_taxonomy
. La documentación dice que puedes establecerlo en false
, o como una cadena, pero no especifica qué pasará si lo estableces como verdadero. Esperemos que WordPress sea lo suficientemente inteligente para sustituirlo con algo más útil, pero como no lo estás estableciendo explícitamente a algo diferente al nombre de tu taxonomía, simplemente elimínalo por ahora (eso significa que se usará talktype
en su lugar).
Acabo de poner esto en un tema vacío y parece funcionar bien (es decir, imprime una consulta SQL que incluye la consulta de metadatos). Ejecutar una consulta también funciona correctamente:
functions.php
// Agregar tipos de contenido "Talk" y "Event"
function nc_custom_post_types() {
register_post_type( 'talk',
array(
'labels' => array(
'name' => __( 'Talks' ),
'singular_name' => __( 'Talk' )
),
'public' => true,
'has_archive' => true,
)
);
// Agregar nueva taxonomía "talktype" al tipo de contenido "talk"
register_taxonomy('talktype', 'talk', array(
'hierarchical' => true,
// Este array de opciones controla las etiquetas mostradas en la interfaz de administración de WordPress
'labels' => array(
'name' => _x( 'Tipos de Talk', 'nombre general de taxonomía' ),
'singular_name' => _x( 'Tipo de Talk', 'nombre singular de taxonomía' ),
'search_items' => __( 'Buscar Tipos de Talk' ),
'all_items' => __( 'Todos los Tipos de Talk' ),
'parent_item' => __( 'Tipo de Talk Padre' ),
'parent_item_colon' => __( 'Tipo de Talk Padre:' ),
'edit_item' => __( 'Editar Tipo de Talk' ),
'update_item' => __( 'Actualizar Tipo de Talk' ),
'add_new_item' => __( 'Agregar Nuevo Tipo de Talk' ),
'new_item_name' => __( 'Nombre del Nuevo Tipo de Talk' ),
'menu_name' => __( 'Tipos de Talk' ),
),
// Controlar los slugs usados para esta taxonomía
'rewrite' => array(
'slug' => 'talktype',
'with_front' => false, // No mostrar la base de categoría antes de "/locations/"
'hierarchical' => true // Esto permitirá URLs como "/locations/boston/cambridge/"
),
));
}
add_action( 'init', 'nc_custom_post_types' );
/* Para propósitos de prueba
add_action('wp', 'test');
function test() {
$nextSundayTalkArgs = array(
'post_type' => 'talk',
'posts_per_page' => 1,
'tax_query' => array(
array(
'taxonomy' => 'talktype',
'field' => 'slug',
'terms' => 'sunday-talk'
)
)
);
$nextSundayTalkQuery = new WP_Query( $nextSundayTalkArgs );
var_dump($nextSundayTalkQuery->request);
die();
}
*/
function sunday_query_args() {
$nextSundayTalkArgs = array(
'post_type' => 'talk',
'posts_per_page' => 1,
'tax_query' => array(
array(
'taxonomy' => 'talktype',
'field' => 'slug',
'terms' => 'sunday-talk'
)
)
);
return $nextSundayTalkArgs;
}
index.php
<?php get_header(); ?>
<?php query_posts(sunday_query_args()); ?>
<div id="content">
<?php while ( have_posts() ) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<h1 class="entry-title"><?php the_title(); ?></h1>
<div class="entry-content">
<?php the_content(); ?>
</div>
</article>
<?php endwhile; ?>
</div>
<?php get_sidebar(); ?>
<?php get_footer(); ?>
EDITADO: Acabo de probar ejecutar tu código sin modificar, y eso también funciona. Por lo que puedo ver, la parte 0 = 1
en el SQL se genera cuando no se encuentra la taxonomía o el término especificado, lo que significa que no se puede crear el INNER JOIN
. Asegúrate de tener el término en tu base de datos, y que tanto el término como la taxonomía aparezcan en la pantalla de edición de tu tipo de contenido.
Sé que has verificado y vuelto a verificar el contenido de los términos en tu base de datos, así que si esto aún no resuelve tu problema, intenta aislarlo más. Comienza usando una instalación limpia de WordPress agregando solo el código que proporcioné arriba, añadiendo un contenido de tipo talk
y asignándole el término sunday-talk
. Eso funciona bien cuando lo pruebo. También intenta ejecutar manualmente el SQL directamente en tu base de datos, si eso no funciona, es seguro decir que la relación post/término no existe. La consulta SQL resultante debería verse así (asegúrate de cambiar el valor de wp_term_relationships.term_taxonomy_id
):
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (4) ) AND wp_posts.post_type = 'talk' AND (wp_posts.post_status = 'publish') GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 1

Hola Simon, muchas gracias por tu ayuda. Las cosas están mejorando - el var_dump($nextSundayTalkQuery->request);
está devolviendo una consulta "saludable" cuando pruebo el código como lo has planteado. Eso sugiere primero que la forma en que estaba llamando mis funciones register_post_type
y register_taxonomy
estaba causando un problema. Ahora que eso funciona, parece que hay un problema con mi bucle de publicaciones, ya que la página ahora se cierra en este punto. if ( $nextSundayTalkQuery->have_posts() ) : while ( $nextSundayTalkQuery->have_posts() ) : $nextSundayTalkQuery->the_post();
es lo que estoy usando.

No estoy seguro de qué está mal - no había sospechado esto como un problema hasta ahora porque funciona bien sin el tax_query involucrado.

@PeteG Cuando dices 'se cierra' ¿quieres decir que la página no se renderiza? ¿puedes configurar http://codex.wordpress.org/WP_DEBUG y pegar el mensaje de error? :)

Gracias :) Recibo:
`Notice: Undefined variable: nextSundayTalkQuery in index.php on line 13
Fatal error: Call to a member function have_posts() on a non-object in index.php on line 13`

Pude ejecutar exitosamente una consulta con while ($nextSundayTalkQuery->have_posts()) { $nextSundayTalkQuery->the_post(); the_title(); }
básicamente reemplazando la línea de var_dump
en mi ejemplo. ¿Mantienes todo el código en index.php
o lo has dividido de alguna manera? Undefined variable: nextSundayTalkQuery
solo puede significar una cosa - que $nextSundayTalkQuery no está definido. Haz var_dump($nextSundayTalkQuery);
para ver qué contiene. Si has ejecutado $nextSundayTalkQuery = new WP_Query( $nextSundayTalkArgs );
antes, debería ser un objeto WP_Query.

Funciona en la función (si lo pongo donde está el var_dump
en tu ejemplo), pero no en mi index.php
por alguna razón. Las taxonomías / tipos de post / filtros de posts están en functions.php
, y mi loop está en index.php
. Al hacer un var_dump
en mi index.php devuelve NULL
.

Creo que mi problema es que todavía soy muy nuevo en WordPress, por lo que probablemente no esté estructurando mi tema correctamente. functions.php
siempre ha funcionado, así que asumí que WordPress lo llamaba automáticamente, ya que en realidad no se llama en ningún lugar de mi index.php
(pero todo lo demás en él parece funcionar).

functions.php
se incluirá automáticamente, pero quizás tus archivos de plantilla no pueden acceder a todo lo que necesitan debido al alcance de las funciones. Actualizaré mi respuesta en un momento con una solución que debería funcionar.

He actualizado mi ejemplo con una función llamada sunday_query_args()
que puedes usar como argumento de función para query_posts()
(o WP_Query
si lo necesitas).

¡Victoria :) Muchas gracias! Ahora necesito entender a) qué había en mi diseño original del functions.php
que no funcionaba, y b) qué hacen realmente tus cambios :) Parece que no necesito un "argumento de función" para mis otras WP_Query
en la misma página, ¿podrías explicar un poco qué hace y por qué lo necesito, por favor?

¡Genial! query_posts se ejecutará automáticamente por WordPress usando variables de consulta del query string del servidor web. Eso significa que obtendrá los 10 posts más recientes en index.php, y una página específica en page.php. Leer la documentación debería ayudarte a comenzar. También echa un vistazo a WP_Query y get_posts e intenta comprender sus similitudes y diferencias.
