Taxonomy personalizată și Tax_Query

5 feb. 2013, 17:10:37
Vizualizări: 31.1K
Voturi: 7

Am avut multe probleme în a face să funcționeze un WP_Query cu un tax_query pe taxonomia mea personalizată.

Sunt 99.9% sigur că register_taxonomy este corect, deoarece pot eticheta articole cu termenul potrivit, îl văd în baza de date, iar termenul corect este returnat cu această funcție: http://pastebin.com/18Aj1ysT.

Dar când folosesc un tax_query în WP_Query, nu primesc niciun articol. Query-ul meu este:

$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 );

Funcționează perfect fără 'tax_query'. Dacă folosesc ceva de genul 'talktype' => 'sunday-talk' în schimb, folosind query_var când înregistrez taxonomia, pur și simplu ignoră linia ca și cum nu ar fi acolo și afișează orice talk (în loc să spună "no posts").

Inserarea <?php echo $GLOBALS['nextSundayTalkQuery']->request; ?> îmi returnează următoarele:

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

Folosind cod identic pentru a interoga taxonomia implicită "category" din WordPress funcționează bine, deci pare să fie legat de taxonomia mea personalizată sau tipul de postare. Pentru a economisi spațiu în această postare, codul pentru tipul meu de postare personalizat este aici:

http://pastebin.com/LxKt2pv5

iar codul taxonomiei mele personalizate este aici:

http://pastebin.com/NxuuxKuG

Am încercat să includ 'include_children' => false așa cum s-a sugerat, dar fără succes.

Aș aprecia orice ajutor, deoarece această problemă a fost nerezolvabilă timp de luni de zile cu multe persoane încercând (și eșuând, din păcate) să înțeleagă ce este greșit.

2
Comentarii

0=1 probabil înseamnă că nu a găsit nimic care să se potrivească cu taxonomia și termenii tăi. Verifică ortografia taxonomiei în baza de date.

Otto Otto
6 feb. 2013 04:19:30

Mulțumesc, Otto. Aș vrea să fie o simplă greșeală de genul acesta, dar am verificat de mai multe ori taxonomia și termenii. Tot nu reușesc să înțeleg. Totul pare în regulă în baza de date - cum am menționat, nici măcar nu funcționează când folosesc ID-uri în loc de slug-uri.

Pete Gale Pete Gale
6 feb. 2013 12:57:51
Toate răspunsurile la întrebare 1
11

În primul rând, apelezi register_post_type pe init și register_taxonomy pe after_setup_theme, care este apelat după init. Aceasta înseamnă că taxonomia personalizată nu va fi disponibilă la înregistrarea tipului de postare. Aș sugera să elimini cuvântul cheie taxonomies din tabloul de argumente al register_post_type și să înregistrezi manual taxonomia ulterior. În exemplul tău, se pare că creezi legătura dintre tipul de postare și taxonomie de două ori.

De asemenea, nu sunt sigur despre 'query_var' => true, în tabloul de argumente al register_taxonomy. Documentația spune că îl poți seta la false sau la un șir de caractere, dar nu specifică ce se va întâmpla dacă îl setezi la true. Sperăm că WordPress va fi suficient de inteligent pentru a-l înlocui cu ceva mai util, dar deoarece nu îl setezi explicit la altceva decât numele taxonomiei, elimină-l deocamdată (asta înseamnă că va fi folosit talktype în loc).

Tocmai am testat acest lucru într-o temă goală și pare să funcționeze bine (adică afișează o interogare SQL care include interogarea meta). De asemenea, rularea unei interogări funcționează corect:

functions.php

// Adaugă tipurile de postare "Talk" și "Event"
function nc_custom_post_types() {
    register_post_type( 'talk',
        array(
            'labels' => array(
                'name' => __( 'Talks' ),
                'singular_name' => __( 'Talk' )
            ),
            'public' => true,
            'has_archive' => true,
        )
    );


    // Adaugă noua taxonomie "talktype" la tipul de postare "talk"
    register_taxonomy('talktype', 'talk', array(
        'hierarchical' => true,
        // Acest tablou de opțiuni controlează etichetele afișate în interfața de administrare WordPress
        'labels' => array(
            'name' => _x( 'Talk Types', 'taxonomy general name' ),
            'singular_name' => _x( 'Talk Type', 'taxonomy singular name' ),
            'search_items' =>  __( 'Search Talk Types' ),
            'all_items' => __( 'All Talk Types' ),
            'parent_item' => __( 'Parent Talk Type' ),
            'parent_item_colon' => __( 'Parent Talk Type:' ),
            'edit_item' => __( 'Edit Talk Type' ),
            'update_item' => __( 'Update Talk Type' ),
            'add_new_item' => __( 'Add New Talk Type' ),
            'new_item_name' => __( 'New Talk Type Name' ),
            'menu_name' => __( 'Talk Types' ),
        ),
        // Controlează slug-urile folosite pentru această taxonomie
        'rewrite' => array(
            'slug' => 'talktype',
            'with_front' => false, // Nu afișa baza categoriei înainte de "/locations/"
            'hierarchical' => true // Acest lucru va permite URL-uri precum "/locations/boston/cambridge/"
        ),
    ));
}
add_action( 'init', 'nc_custom_post_types' );

/* Pentru teste
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(); ?>

EDIT: Tocmai am încercat să rulez codul tău nemodificat, și acesta funcționează de asemenea. Din câte pot să văd, partea 0 = 1 din SQL este generată atunci când fie taxonomia, fie termenul specificat nu este găsit, ceea ce înseamnă că INNER JOIN nu poate fi creat. Asigură-te că ai termenul în baza de date și că atât termenul, cât și taxonomia apar în ecranul de editare al tipului de postare.

Știu că ai verificat și dublu-verificat conținutul termenilor din baza ta de date, așa că dacă aceasta încă nu rezolvă problema ta, încearcă să izolezi problema mai departe. Începe prin a folosi o instalare curată de WordPress, adăugând doar codul pe care l-am furnizat mai sus, adăugând o postare talk și atribuindu-i termenul sunday-talk. Asta funcționează bine când încerc eu. De asemenea, încearcă să rulezi manual SQL direct pe baza ta de date, dacă asta nu funcționează, poți spune cu siguranță că relația post/termen nu există. Interogarea SQL rezultată ar trebui să arate cam așa (asigură-te să schimbi valoarea wp_term_relationships.term_taxonomy_id totuși):

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
Comentarii

Salut Simon, îți mulțumesc mult pentru ajutor. Lucrurile par să meargă mai bine - var_dump($nextSundayTalkQuery->request); returnează o interogare "sănătoasă" când încerc codul așa cum l-ai structurat tu. Asta sugerează inițial că modul în care apelam funcțiile mele register_post_type și register_taxonomy provoca o problemă. Acum că asta funcționează, se pare că există o problemă cu bucla mea de postări, deoarece pagina acum se blochează în acest punct. if ( $nextSundayTalkQuery->have_posts() ) : while ( $nextSundayTalkQuery->have_posts() ) : $nextSundayTalkQuery->the_post(); este ceea ce folosesc.

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

Nu sunt sigur ce e în neregulă cu asta - nu bănuisem că asta ar fi o problemă până acum pentru că funcționează ok fără tax_query implicat.

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

@PeteG Când spui "se blochează", te referi că pagina nu se afișează? poți să setezi http://codex.wordpress.org/WP_DEBUG și să lipesti mesajul de eroare :)

Tom Tom
18 feb. 2013 21:28:00

Mulțumesc :) Am primit:

`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

Am reușit să rulez cu succes un query cu while ($nextSundayTalkQuery->have_posts()) { $nextSundayTalkQuery->the_post(); the_title(); } practic înlocuind linia cu var_dump din exemplul meu. Păstrezi tot codul în index.php sau l-ai împărțit cumva? Undefined variable: nextSundayTalkQuery poate însemna doar un lucru - că $nextSundayTalkQuery nu este setat. Fă var_dump($nextSundayTalkQuery); ca să vezi ce conține. Dacă ai rulat $nextSundayTalkQuery = new WP_Query( $nextSundayTalkArgs ); înainte, ar trebui să fie un obiect WP_Query.

Simon Simon
18 feb. 2013 21:45:01

Funcționează în funcție (dacă o pun unde este var_dump în exemplul tău), dar nu și în index.php meu din nu știu ce motiv. Taxonomiile / tipurile de postări / filtrele de postări sunt în functions.php, iar loop-ul meu este în index.php. Dacă fac un var_dump în index.php, returnează NULL.

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

Cred că problema mea este că sunt încă foarte nou în WordPress, așa că probabil nu configurez tema corect. functions.php a funcționat întotdeauna, așa că am presupus că WordPress îl apelează automat, deoarece nu este apelat nicăieri în index.php-ul meu (dar tot restul din el pare să funcționeze).

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

functions.php va fi inclus automat, dar poate fișierele tale de template nu au acces la tot ce este necesar din cauza domeniului de funcții. Voi actualiza răspunsul meu imediat cu o soluție care ar trebui să funcționeze.

Simon Simon
18 feb. 2013 22:06:50

Am actualizat exemplul meu cu o funcție numită sunday_query_args() pe care o poți folosi ca argument pentru query_posts() (sau WP_Query dacă ai nevoie).

Simon Simon
18 feb. 2013 22:12:14

Victorie :) Mulțumesc mult! Acum trebuie să înțeleg a) ce anume din structura originală a fișierului meu functions.php nu funcționa corect și b) ce anume fac modificările tale :) Pare că nu am nevoie de un "argument de funcție" pentru celelalte interogări WP_Query de pe aceeași pagină, așa că poți să explici puțin ce face acesta și de ce am nevoie de el, te rog?

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

Minunat! query_posts va fi rulat automat de WordPress folosind variabilele de interogare din șirul de interogare al serverului web. Asta înseamnă că va prelua cele mai recente 10 articole pe index.php și o anumită pagină pe page.php. Citirea documentației ar trebui să te ajute să începi. Aruncă o privire și asupra WP_Query și get_posts și încearcă să înțelegi asemănările și diferențele dintre ele.

Simon Simon
18 feb. 2013 23:51:19
Arată celelalte 6 comentarii