Visualizzare tutti i post in un custom post type, raggruppati per tassonomia personalizzata
Sto lavorando su una pagina dei membri dove utilizzo un custom post type con una tassonomia personalizzata. Il mio custom post type si chiama member
e la mia tassonomia personalizzata si chiama member_groups
.
Voglio elencare tutti i membri ma raggrupparli nei loro rispettivi gruppi.
Per essere chiaro, ho 35 membri divisi in 9 gruppi – quindi invece di fare la stessa query nove volte, voglio farla una volta sola ma raggruppare i membri insieme, in modo che Membro1, Membro4 e Membro11 siano raggruppati insieme in un gruppo chiamato "Marketing".
Sto usando WP_Query
per recuperare tutti i post sotto il post type member. Ho provato diversi tentativi ma senza ottenere risultati soddisfacenti.
Come posso ottenere questo risultato?
Quindi, potresti considerare di automatizzare le query multiple.
Per prima cosa, ottieni la lista dei termini nella tua tassonomia personalizzata, usando get_terms()
:
<?php
$member_group_terms = get_terms( 'member_group' );
?>
Poi, scorri ciascuno di essi, eseguendo una nuova query ogni volta:
<?php
foreach ( $member_group_terms as $member_group_term ) {
$member_group_query = new WP_Query( array(
'post_type' => 'member',
'tax_query' => array(
array(
'taxonomy' => 'member_group',
'field' => 'slug',
'terms' => array( $member_group_term->slug ),
'operator' => 'IN'
)
)
) );
?>
<h2><?php echo $member_group_term->name; ?></h2>
<ul>
<?php
if ( $member_group_query->have_posts() ) : while ( $member_group_query->have_posts() ) : $member_group_query->the_post(); ?>
<li><?php echo the_title(); ?></li>
<?php endwhile; endif; ?>
</ul>
<?php
// Resetta le variabili, per sicurezza
$member_group_query = null;
wp_reset_postdata();
}
?>
Non vedo nulla di particolarmente sbagliato in questo approccio, anche se potrebbe avere una capacità limitata di scalare (cioè, se hai centinaia o migliaia di membri, o termini member_group, potresti riscontrare problemi di prestazioni).

Sì, funziona perfettamente. Solo un problema che ho. Voglio visualizzare i campi personalizzati così <?php get_post_meta($member_group_term->ID, 'job_title', true);?> ma non ha funzionato. Ho anche provato con $post->ID ma comunque non ha funzionato, potresti aiutarmi @Chip Bennett per favore?

Mi rendo conto che è passato oltre un decennio, ma c'è qualcosa di seriamente sbagliato in questo approccio, visto che stai creando una query separata per ogni termine. Quando parliamo di un piccolo numero di termini, allora non vedremo un grande impatto sulle prestazioni. Ma una volta che superiamo i 20-30 termini, questo tipo di ciclo influenzerà seriamente i tempi di caricamento e il tempo di risposta del server. Il mio suggerimento qui è in realtà quello di recuperare tutti i post e poi eseguire un usort
dopo il fatto. In questo modo, non sovraccarichi il database con un sacco di query e ottieni i tuoi risultati in due passaggi.

Ho trovato una soluzione utilizzando una query personalizzata e poi raggruppandola con il nome del termine:
SELECT *
FROM wp_term_taxonomy AS cat_term_taxonomy
INNER JOIN wp_terms AS cat_terms ON cat_term_taxonomy.term_id = cat_terms.term_id
INNER JOIN wp_term_relationships AS cat_term_relationships ON cat_term_taxonomy.term_taxonomy_id = cat_term_relationships.term_taxonomy_id
INNER JOIN wp_posts AS cat_posts ON cat_term_relationships.object_id = cat_posts.ID
INNER JOIN wp_postmeta AS meta ON cat_posts.ID = meta.post_id
WHERE cat_posts.post_status = 'publish'
AND meta.meta_key = 'active'
AND meta.meta_value = 'active'
AND cat_posts.post_type = 'member'
AND cat_term_taxonomy.taxonomy = 'member_groups'
Poi semplicemente utilizzando un normale ciclo foreach posso estrarre le informazioni che mi interessano.
Ma sono comunque interessato a un altro metodo se esiste, magari utilizzando le funzioni native di WordPress.

Ho appena aggiunto un metodo alternativo. Tendo a evitare tutto ciò che richiede query SQL dirette.

Sono contento di vedere questa risposta contrassegnata come corretta, anche se la query smetterà di funzionare in WordPress se lo schema dovesse cambiare in futuro... Il concetto di raccoglierle tutte in una singola query è la risposta corretta. L'iterazione per raggruppare le tassonomie in PHP non scalerà bene quanto questa soluzione.

ancora più semplice:
$terms = get_terms('tax_name');
$posts = array();
foreach ( $terms as $term ) {
$posts[$term->name] = get_posts(array( 'posts_per_page' => -1, 'post_type' => 'post_type', 'tax_name' => $term->name ));
}
All'interno dell'array risultante $posts, ogni termine di tassonomia è la chiave per un array annidato che contiene i relativi post.

Avevo esattamente questa necessità e la soluzione di Chip ha funzionato, tranne per una cosa: 'field' => 'slug'
è obbligatorio.
foreach ( $service_categories as $category ) {
$services = new WP_Query(
array(
'post_type' => 'service',
'tax_query' => array(
array(
'taxonomy' => 'service_category',
'terms' => array( $category->slug ),
'operator' => 'IN',
'get' => 'all',
'field' => 'slug'
)
)
)
); ?>
<h2><?php echo $category->slug; ?></h2>
<?php if ( $services->have_posts() ) { // qui va il loop ?>
Inoltre, avevo bisogno che il risultato fosse piatto, quindi qui è impostato 'get' => 'all'
.
Spero che questo possa aiutare qualcun altro.

Ho dovuto implementare questa soluzione in un progetto alcuni anni fa. Risposta simile a djb, ma con qualche dettaglio in più. Questo codice mostrerà tutti i nomi delle tassonomie come intestazioni h3, con un elenco puntato di ogni titolo di post collegato alla rispettiva pagina dettaglio.
<?php // Mostra tutti i nomi delle Tassonomie con i rispettivi elementi
$terms = get_terms('member_groups');
foreach( $terms as $term ):
?>
<h3><?php echo $term->name; // Stampa il nome del termine ?></h3>
<ul>
<?php
$posts = get_posts(array(
'post_type' => 'member',
'taxonomy' => $term->taxonomy,
'term' => $term->slug,
'nopaging' => true, // per mostrare tutti i post in questa tassonomia, si potrebbe usare anche 'numberposts' => -1
));
foreach($posts as $post): // inizia il ciclo attraverso i post di questa tassonomia
setup_postdata($post); // prepara i dati del post per l'uso nel loop (abilita the_title(), etc senza specificare un ID post)
?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endforeach; ?>
</ul>
<?php endforeach; ?>

$query = new WP_Query(
array (
'post_type' => 'member',
'orderby' => 'meta_value',
'meta_key' => 'member_group'
)
);
Poi, quando esegui il loop attraverso questa query, potresti semplicemente usare un if seguendo queste linee (in pseudocodice PHP)
$groupName = "";
$counter = 0;
if havePosts: while havePosts: thePost
if( $groupName != post->meta_value )
{
if ($counter > 0)
{
</ul>
}
<h1>Un nome di gruppo</h1>
<ul>
<li>nome membro</li>
}
else
{
<li>nome membro</li>
}
endwhile;endif
</ul>
Spero che questo ti aiuti. Penso che tu stessi rendendo questa cosa molto più complicata del necessario.
Maggiori informazioni: http://codex.wordpress.org/Class_Reference/WP_Query#Taxonomy_Parameters

Bene, è un thread vecchio, ma se qualcuno passa di qui come ho fatto io, questo potrebbe aiutare. L'idea è modificare la query principale così da non dover intervenire sui template e generare nuove query e loop...
PS: Da testare ancora su database grandi. Nel mio caso ha dato risultati soddisfacenti.
function grouped_by_taxonomy_main_query( $query ) {
if ( $query->is_home() && $query->is_main_query() ) { // Esegui solo sulla homepage
$post_ids = array();
$terms = get_terms('my_custom_taxonomy');
foreach ( $terms as $term ) {
$post_ids = array_merge( $post_ids, get_posts( array(
'posts_per_page' => 4, // come preferisci...
'post_type' => 'my_custom_post_type', // Se necessario... Di default sono i post
'fields' => 'ids', // vogliamo solo gli ID da usare dopo in 'post__in'
'tax_query' => array( array( 'taxonomy' => $term->taxonomy, 'field' => 'term_id', 'terms' => $term->term_id, )))) // otteniamo i post nel termine corrente
);
}
$query->query_vars['post_type'] = 'my_custom_post_type'; // Ancora, se necessario... Di default sono i post
$query->query_vars['posts_per_page'] = 16; // Se necessario...
$query->query_vars['post__in'] = $post_ids; // Filtriamo con gli ID dei post ottenuti sopra
$query->query_vars['orderby'] = 'post__in'; // Manteniamo l'ordine generato nel loop dei termini
$query->query_vars['ignore_sticky_posts'] = 1; // Se non vuoi che i post sticky alterino l'ordine
}
}
// Aggancio la mia funzione all'azione pre_get_posts
add_action( 'pre_get_posts', 'grouped_by_taxonomy_main_query' );
