Afișarea tuturor postărilor dintr-un tip de postare personalizat, grupate după o taxonomie personalizată

4 nov. 2011, 14:09:32
Vizualizări: 64.2K
Voturi: 22

Lucrez la o pagină de membri unde folosesc un tip de postare personalizat cu o taxonomie personalizată. Tipul meu de postare personalizat se numește member și taxonomia mea personalizată se numește member_groups.

Vreau să listez toți membrii, dar să îi grupez împreună în grupurile lor respective.

Pentru a fi mai clar, am 35 de membri împărțiți în 9 grupuri – deci în loc să fac aceeași interogare de nouă ori, vreau să o fac o singură dată dar să îi grupez împreună, astfel încât Membru1, Membru4 și Membru11 să fie grupați împreună într-un grup numit "Marketing".

Folosesc WP_Query pentru a recupera toate postările de tipul member. Am încercat diferite abordări dar fără un rezultat de succes.

Cum pot realiza acest lucru?

0
Toate răspunsurile la întrebare 7
2
34

Așadar, ai putea lua în considerare automatizarea interogărilor multiple.

Mai întâi, obține lista de termeni din taxonomia personalizată, folosind get_terms():

<?php
$member_group_terms = get_terms( 'member_group' );
?>

Apoi, parcurge fiecare termen, rulând o nouă interogare de fiecare dată:

<?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
    // Resetează variabilele, pentru precauție
    $member_group_query = null;
    wp_reset_postdata();
}
?>

Nu văd nimic în mod special greșit în această abordare, deși poate avea o capacitate limitată de scalare (adică, dacă ai sute sau mii de membri sau termeni în member_group, s-ar putea să întâmpini probleme de performanță).

25 ian. 2012 16:31:55
Comentarii

Da, funcționează perfect. Doar o problemă am. Vreau să afișez câmpuri personalizate astfel <?php get_post_meta($member_group_term->ID, 'job_title', true);?> dar nu a funcționat. Am încercat și cu $post->ID dar tot nu a funcționat, poți să mă ajuți @Chip Bennett te rog?

Ana DEV Ana DEV
21 dec. 2015 09:53:23

Îmi dau seama că au trecut peste un deceniu, dar există ceva foarte greșit în această abordare, și anume că creezi o interogare separată pentru fiecare termen. Când vorbim despre un număr mic de termeni, nu vom observa un impact semnificativ asupra performanței. Dar odată ce trecem de 20-30 de termeni, acest tip de buclă va afecta serios viteza de încărcare și timpul de răspuns al serverului. Sugestia mea este să obții toate articolele și apoi să rulezi un usort după aceea. În acest fel, nu vei încărca baza de date cu o mulțime de interogări și vei obține rezultatele în doi pași.

maiorano84 maiorano84
26 ian. 2025 21:58:23
3

Am găsit o soluție prin utilizarea unei interogări personalizate și apoi grupând-o cu numele termenului:

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'

Apoi, prin simpla utilizare a unei interogări obișnuite foreach, pot extrage doar informațiile dorite.

Dar sunt încă interesat de o altă metodă, dacă există, poate prin utilizarea funcțiilor proprii ale WordPress.

4 nov. 2011 14:31:36
Comentarii

Tocmai am adăugat o metodă alternativă. Am tendința să evit orice necesită interogări SQL brute.

Chip Bennett Chip Bennett
25 ian. 2012 16:32:45

Mă bucur să văd acest răspuns marcat ca fiind corect, chiar dacă interogarea nu va mai funcționa în WordPress dacă schema se schimbă la un moment dat... Conceptul de a le colecta pe toate într-o singură interogare este răspunsul corect. Iterarea pentru a grupa taxonomiile în PHP nu va scala la fel de bine precum această soluție.

wowo_999 wowo_999
13 nov. 2013 01:03:29

OMG, Vorbești serios când scrii interogare brută? Probabil că tocmai ai intrat în lumea WP sau nu te-ai obosit niciodată să urmezi standardele sale. Răspunsul nu ar trebui să fie selectat.

pixelngrain pixelngrain
1 iul. 2020 10:35:13
0

chiar mai simplu:

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

În cadrul array-ului rezultat $posts, fiecare termen de taxonomie este cheia către un array imbricat ce conține postările asociate.

4 apr. 2012 16:12:29
0

Am avut exact aceeași nevoie, iar soluția lui Chip a funcționat, cu excepția unui lucru: 'field' => 'slug' este obligatoriu.

    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() ) {  // aici intră logica de buclă ?>

De asemenea, aveam nevoie ca afișarea rezultată să fie plată, așa că am setat 'get' => 'all' aici.

Sper că acest lucru va ajuta pe altcineva.

24 ian. 2013 03:38:15
0

A trebuit să implementez acest lucru într-un proiect acum câțiva ani. Un răspuns similar cu cel al lui djb, dar cu mai multe detalii. Acest cod va afișa toate numele taxonomiilor ca elemente h3, cu o listă cu puncte a fiecărui titlu de articol legat la pagina sa de detaliu.

<?php // Afișează toate numele de Taxonomii cu elementele lor respective
$terms = get_terms('member_groups');
foreach( $terms as $term ):
?>                          
    <h3><?php echo $term->name; // Afișează numele termenului ?></h3>                          
    <ul>
      <?php                         
          $posts = get_posts(array(
            'post_type' => 'member',
            'taxonomy' => $term->taxonomy,
            'term' => $term->slug,                                  
            'nopaging' => true, // pentru a afișa toate articolele din această taxonomie, se poate folosi și 'numberposts' => -1
          ));
          foreach($posts as $post): // începe ciclul prin articolele acestei taxonomii
            setup_postdata($post); // inițializează datele articolului pentru utilizare în buclă (activează the_title(), etc fără a specifica un ID de articol)
      ?>        
          <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>    
        <?php endforeach; ?>
    </ul>                                                   
<?php endforeach; ?>
11 feb. 2015 19:55:36
0
$query = new WP_Query( 
   array ( 
      'post_type' => 'membru', 
      'orderby'   => 'meta_value', 
      'meta_key'  => 'grup_membru' 
   ) 
);

Apoi, când parcurgi această interogare, poți folosi pur și simplu o condiție if de genul următor (în pseudocod php)

$numeGrup = "";
$counter = 0;
if havePosts: while havePosts: thePost

if( $numeGrup != post->meta_value )
{
if ($counter > 0)
{
</ul>
}
<h1>Numele unui grup</h1>
<ul>
<li>nume membru</li>
}
else
{
<li>nume membru</li>
}

endwhile;endif

</ul>

Sper că acest lucru te ajută. Cred că ai făcut totul mult mai complicat decât era necesar.

Mai multe informații: http://codex.wordpress.org/Class_Reference/WP_Query#Taxonomy_Parameters

5 nov. 2011 07:01:14
0

Ei bine, este un thread vechi, dar dacă cineva trece pe aici cum am făcut și eu, acest lucru ar putea ajuta. Ideea este să modificăm interogarea principală, astfel încât să nu fie nevoie să mergem la șabloane și să generăm noi interogări și bucle...

PS: Încă nu a fost testat pe baze de date mari. În cazul meu a fost satisfăcător.

function grouped_by_taxonomy_main_query( $query ) {

    if ( $query->is_home() && $query->is_main_query() ) { // Rulează doar pe pagina de start

        $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, // după cum dorești...
                'post_type' => 'my_custom_post_type', // Dacă este necesar... Implicit sunt postări
                'fields' => 'ids', // vrem doar id-urile pentru a le folosi mai târziu în 'post__in'
                'tax_query' => array( array( 'taxonomy' => $term->taxonomy, 'field' => 'term_id', 'terms' => $term->term_id, )))) // obținerea postărilor din termenul curent
            );
        }

        $query->query_vars['post_type'] = 'my_custom_post_type'; // Din nou, dacă este necesar... Implicit sunt postări
        $query->query_vars['posts_per_page'] = 16; // Dacă este necesar...
        $query->query_vars['post__in'] = $post_ids; // Filtrarea cu id-urile postărilor obținute mai sus
        $query->query_vars['orderby'] = 'post__in'; // Aici păstrăm ordinea generată în bucla de termeni
        $query->query_vars['ignore_sticky_posts'] = 1; // Dacă nu dorești ca postările sticky să schimbe ordinea

    }
}

// Conectează funcția de mai sus la acțiunea pre_get_posts
add_action( 'pre_get_posts', 'grouped_by_taxonomy_main_query' );
22 apr. 2017 09:33:04