Taxonomía Personalizada y Tax_Query

5 feb 2013, 17:10:37
Vistas: 31.1K
Votos: 7

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í:

http://pastebin.com/LxKt2pv5

y mi código de taxonomía personalizada está aquí:

http://pastebin.com/NxuuxKuG

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.

2
Comentarios

El 0=1 probablemente significa que no encontró nada que coincida con tu taxonomía y términos. Revisa la ortografía de la taxonomía en la base de datos.

Otto Otto
6 feb 2013 04:19:30

Gracias Otto. Por mucho que me encantaría que fuera un error simple como este, he ido y venido revisando la taxonomía y los términos varias veces. Todavía no entiendo qué pasa. Todo parece estar bien en la base de datos - como mencioné, ni siquiera funciona cuando uso IDs en lugar de slugs.

Pete Gale Pete Gale
6 feb 2013 12:57:51
Todas las respuestas a la pregunta 1
11

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
18 feb 2013 18:42:46
Comentarios

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.

Pete Gale Pete Gale
18 feb 2013 20:55:55

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.

Pete Gale Pete Gale
18 feb 2013 20:59:26

@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? :)

Tom Tom
18 feb 2013 21:28:00

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`

Pete Gale Pete Gale
18 feb 2013 21:37:57

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.

Simon Simon
18 feb 2013 21:45:01

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.

Pete Gale Pete Gale
18 feb 2013 22:04:37

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).

Pete Gale Pete Gale
18 feb 2013 22:05:38

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.

Simon Simon
18 feb 2013 22:06:50

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).

Simon Simon
18 feb 2013 22:12:14

¡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?

Pete Gale Pete Gale
18 feb 2013 22:35:27

¡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.

Simon Simon
18 feb 2013 23:51:19
Mostrar los 6 comentarios restantes