Query WP_Query di Tassonomia Personalizzata per Tutti i Termini di una Tassonomia
Esiste un modo semplice per interrogare tutti i post che sono etichettati con qualsiasi termine di una particolare tassonomia?
Conosco questa tecnica:
$custom_taxonomy_query = new WP_Query(
array(
'taxonomy_name' => 'term_slug',
)
);
Ma vorrei poter passare un carattere jolly al posto di term_slug, o magari semplicemente una stringa vuota. Questo mi darebbe tutti i post che sono etichettati da qualsiasi termine in quella tassonomia, non solo da un termine specifico.
Grazie per il vostro aiuto, Dave

Mi sono trovato in una situazione simile Dave. Questo codice ha funzionato per le mie esigenze. Non è l'opzione più snella al mondo ma fa bene il suo lavoro:
// Ottieni tutti gli ID dei termini in una tassonomia specifica
$taxonomy = 'taxonomy_name';
$taxonomy_terms = get_terms( $taxonomy, array(
'hide_empty' => 0,
'fields' => 'ids'
) );
// Usa il nuovo argomento tax_query di WP_Query (disponibile dalla versione 3.1)
$taxonomy_query = new WP_Query( array(
'tax_query' => array(
array(
'taxonomy' => $taxonomy,
'field' => 'id',
'terms' => $taxonomy_terms,
),
),
) );
Spero che questo possa aiutare te o chiunque altro stia affrontando lo stesso problema.
Kevin

Qualcosa del genere potrebbe funzionare:
$args = array(
'post_type' => 'post',
'tax_query' => array(
array(
'taxonomy' => 'your_custom_taxonomy', // Sostituisci con la tua tassonomia personalizzata
'operator' => 'EXISTS' // Seleziona i post che hanno almeno un termine in questa tassonomia
),
),
);
$query = new WP_Query( $args ); // Esegue la query
In pratica stai chiedendo qualsiasi post assegnato a qualsiasi termine all'interno di your_custom_taxonomy.

Ciao @Dave Morris:
Hai ragione, WordPress se non hai un termine semplicemente ignorerà la tua tassonomia.
Ci sono tre (3) approcci principali che potresti provare:
Usa una query SQL completa con
$wpdb->get_results()
,Ottieni una lista di
$post->ID
per tutti i post nella tua tassonomia e poi passali usando l'argomento'post__id'
, oppureAnnota l'SQL usato da
WP_Query
con uno degli hook che ti permette di aggiungere unINNER JOIN
SQL riferito alle tabelle della tassonomia.
Cerco di evitare SQL completo in WordPress finché non è strettamente necessario o finché non si tratta semplicemente di restituire una lista di ID. E in questo caso eviterei di estrarre una lista di $post-ID
da usare con l'argomento 'post__id'
perché potrebbe causare problemi di prestazioni e persino di memoria se hai molti post. Quindi ci rimane l'opzione #3.
Ho creato una classe per estendere WP_Query
chiamata PostsByTaxonomy
che utilizza l'hook 'posts_join'
. Puoi vederla qui:
class PostsByTaxonomy extends WP_Query {
var $posts_by_taxonomy;
var $taxonomy;
function __construct($args=array()) {
add_filter('posts_join',array(&$this,'posts_join'),10,2);
$this->posts_by_taxonomy = true;
$this->taxonomy = $args['taxonomy'];
unset($args['taxonomy']);
parent::query($args);
}
function posts_join($join,$query) {
if (isset($query->posts_by_taxonomy)) {
global $wpdb;
$join .=<<<SQL
INNER JOIN {$wpdb->term_relationships} ON {$wpdb->term_relationships}.object_id={$wpdb->posts}.ID
INNER JOIN {$wpdb->term_taxonomy} ON {$wpdb->term_taxonomy}.term_taxonomy_id={$wpdb->term_relationships}.term_taxonomy_id
AND {$wpdb->term_taxonomy}.taxonomy='{$this->taxonomy}'
SQL;
}
return $join;
}
}
Chiameresti questa classe come vedi sotto. L'argomento 'taxonomy'
è obbligatorio ma puoi passare qualsiasi (tutti?) degli altri parametri che WP_Query
si aspetta, come 'posts_per_page'
:
$query = new PostsByTaxonomy(array(
'taxonomy' => 'category',
'posts_per_page' => 25,
));
foreach($query->posts as $post) {
echo " {$post->post_title}\n";
}
Puoi copiare la classe PostsByTaxonomy
nel file functions.php
del tuo tema, oppure puoi usarla all'interno di un file .php
di un plugin che stai scrivendo.
Se vuoi testarla rapidamente ho pubblicato una versione autonoma del codice su Gist che puoi scaricare e copiare nella root del tuo server web come test.php
, modificare per il tuo caso d'uso e poi richiedere dal browser usando un URL come http://example.com/test.php
.
AGGIORNAMENTO
Per escludere i Post in Evidenza dai post inclusi nella query, prova questo:
$query = new PostsByTaxonomy(array(
'taxonomy' => 'category',
'posts_per_page' => 25,
'caller_get_posts' => true,
));
Oppure se è importante per te che la classe PostsByTaxonomy
non includa mai post in evidenza, potresti inserirlo nel costruttore:
function __construct($args=array()) {
add_filter('posts_join',array(&$this,'posts_join'),10,2);
$this->posts_by_taxonomy = true;
$this->taxonomy = $args['taxonomy'];
$args['caller_get_posts'] = true // No Post in Evidenza
unset($args['taxonomy']);
parent::query($args);
}
AGGIORNAMENTO 2
Dopo aver pubblicato quanto sopra ho scoperto che 'caller_get_posts' sarà deprecato e 'ignore_sticky_posts'
sarà utilizzato in WordPress 3.1.

Mike, grazie per il tuo aiuto. Per qualche motivo non riesco a farlo funzionare. Non restituisce solo i post con i termini assegnati dalla mia tassonomia personalizzata. Sembra sempre restituire altri post. Tuttavia, non restituisce tutti i post, quindi sta sicuramente facendo qualcosa... Posso usare la funzione $query->have_posts() per iterare? Nessuno dei due metodi sembra funzionare per me, in ogni caso.

Ah, questo è interessante. Ho trovato la query nel log mysql che ottiene i due post che mi aspetto, e funziona. Ma per qualche motivo, quando eseguo il loop su $query->posts, tornano cinque post. L'unica altra cosa che noto è che subito dopo l'esecuzione della query dei post della tassonomia personalizzata, viene eseguita un'altra query che recupera altri tre post, tramite i loro post_id. E poi immagino che tutti e cinque i post vengano inseriti in un unico array di risultati.

Credo di aver capito. Questa query personalizzata sembra includere i post sticky, anche se non sono in quella tassonomia personalizzata. Hai qualche idea su come gestire correttamente i post sticky, o almeno su come rimuoverli da questa query particolare? Grazie, Dave

Beh, sono "appiccicosi", giusto? :)
È un comportamento strano, credo, ma se usi caller_get_posts=1
dovrebbero sparire:
http://codex.wordpress.org/Function_Reference/query_posts#Sticky_Post_Parameters
Spero che questo ti aiuti.

Quel if(isset($query->posts_by_taxonomy))
è un bel trucco per combinare la metodologia object-oriented con l'approccio agli hook di WordPress.

@Jan Fabry - Sì, grazie! Mi ci sono voluti solo circa 2 anni di tentativi ed errori prima che mi venisse in mente. Ora ovviamente sembra ovvio... :)

Ha funzionato! Grazie mille per il tuo aiuto. Mi piace imparare nuovi trucchi su WordPress, specialmente quelli OO.

@Dave Morris - Prego. A proposito, ho appena scoperto che in WP 3.1 si chiamerà 'ignore_sticky_posts'
.

@MikeSchinkel E per quanto riguarda l'impaginazione? Questo funziona bene, ma l'impaginazione per questa query non funziona come dovrebbe nel mio caso... http://wordpress.stackexchange.com/q/57884/12261

Dovresti semplicemente poter impostare la tassonomia e negare per includere un termine..
Es.
<?php
$your_query = new WP_query;
$your_query->query( array( 'taxonomy' => 'nome-della-tua-tassonomia' ) );
?>
Che sarebbe praticamente lo stesso della query eseguita da un archivio tassonomico.

La linea 1432 di query.php verifica se taxonomy OPPURE term sono vuoti, quindi non puoi semplicemente non passare uno slug... Qualche altra idea?

@t31os - Anche la mia prima reazione è stata quella; in realtà ci sono caduto più di una volta perché continuo a dimenticarlo. Ma @Dave Morris ha ragione; se non è una coppia taxonomy/term allora WP_Query
semplicemente la scarta.

Wow, non lo sapevo, è un po' sciocco in realtà... lezione imparata... :) Mi aspettavo che funzionasse come i parametri meta_key / meta_value (non so perché)...

@t31os - Esatto, purtroppo WP_Query
non è implementato in modo così elegante. Sono quasi 1200 righe di casi speciali hard-coded.

In retrospettiva, ho creato un mix tra i suggerimenti di MikeSchinkel e t31os. È possibile inserirlo nelle query esistenti al volo, ma richiede WordPress 3.1:
Plugin per ottenere un Feed RSS per articoli contenenti qualsiasi termine da una tassonomia.
