Afficher toutes les publications dans un type de publication personnalisé, regroupées par taxonomie personnalisée

18

Je travaille sur une page membre où j'utilise un type de publication personnalisé avec une taxonomie personnalisée. Mon type de publication personnalisé est appelé memberet ma taxonomie personnalisée est appelée member_groups.

Je veux lister tous les membres mais les regrouper dans leurs groupes respectifs.

Donc, pour être clair, j'ai 35 membres répartis en 9 groupes - donc au lieu de faire la même requête neuf fois, je veux le faire une fois mais les regrouper, de sorte que Member1, Member4 et Member 11 soient regroupés en un seul groupe, appelé «Marketing».

J'utilise WP_Querypour récupérer tous les messages sous membre de type de message. J'ai essayé différentes tentatives mais sans résultat.

Comment puis-je y parvenir?

Mestika
la source

Réponses:

29

Vous pouvez donc envisager d'automatiser les multiples requêtes.

Tout d'abord, obtenez la liste des termes dans votre taxonomie personnalisée, en utilisant get_terms():

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

Ensuite, parcourez chacun d'eux, en exécutant une nouvelle requête à chaque fois:

<?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
    // Reset things, for good measure
    $member_group_query = null;
    wp_reset_postdata();
}
?>

Je ne vois rien de particulièrement mauvais avec cette approche, même si elle peut avoir une capacité limitée à évoluer (c'est-à-dire si vous avez des centaines ou des milliers de membres, ou des termes membre_group, vous pouvez voir des problèmes de performances).

Chip Bennett
la source
Oui, il fonctionne parfaitement. Un seul problème que j'ai. Je veux afficher des champs de découpe comme celui-ci <? Php get_post_meta ($ member_group_term-> ID, 'job_title', true);?> Mais cela n'a pas fonctionné. J'ai également essayé avec $ post- > ID mais pas de travail, pourriez-vous aider @Chip Bennett s'il vous plaît?
Anahit DEV
6

J'ai trouvé une solution en utilisant une requête personnalisée, puis en la regroupant avec le nom du terme:

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'

Ensuite, en utilisant simplement une requête foreach régulière, je peux simplement extraire les informations que je veux.

Mais je suis toujours intéressé par une autre façon s'il y en a, peut-être en utilisant les propres fonctions de Wordpress.

Mestika
la source
Je viens d'ajouter une méthode alternative. J'ai tendance à éviter tout ce qui nécessite des requêtes SQL brutes.
Chip Bennett
2
Je suis heureux de voir cela marqué comme la bonne réponse, même si la requête cesse de fonctionner dans wordpress si le schéma change à un moment donné ... Le concept de les rassembler tous dans une seule requête est la bonne réponse. L'itération pour regrouper les taxonomies en échelle php ne sera presque pas aussi bonne que cela.
wowo_999
4

encore plus simple:

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

Dans le tableau $ posts résultant, chaque terme fiscal est la clé d'un tableau imbriqué contenant ses messages.

djb
la source
4

J'avais ce besoin exact, et la solution de Chip a fonctionné, sauf pour une chose: 'field' => 'slug'est requise.

    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() ) {  // loop stuff goes here ?>

J'ai également eu besoin que l'affichage résultant soit plat, c'est donc 'get' => 'all'réglé ici.

J'espère que cela aide quelqu'un d'autre.

gros pull
la source
3
$query = new WP_Query( 
   array ( 
      'post_type' => 'member', 
      'orderby'   => 'meta_value', 
      'meta_key'  => 'member_group' 
   ) 
);

Ensuite, lorsque vous parcourez cette requête, vous pouvez simplement utiliser un if le long de ces lignes (dans le pseudocode php)

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

if( $groupName != post->meta_value )
{
if ($counter > 0)
{
</ul>
}
<h1>A group name</h1>
<ul>
<li>member name</li>
}
else
{
<li>member name</li>
}

endwhile;endif

</ul>

J'espère que ça aide. Je pense que vous rendiez cela beaucoup plus compliqué que nécessaire.

Plus d'informations: http://codex.wordpress.org/Class_Reference/WP_Query#Taxonomy_Parameters

AKnox
la source
3

J'ai dû le faire sur un projet il y a des années. Réponse similaire à djb, juste avec un peu plus de détails. Cela affichera tous vos noms de taxonomie sous forme de h3, avec une liste à puces de chaque titre de poste liée à leur page de détails.

<?php // Output all Taxonomies names with their respective items
$terms = get_terms('member_groups');
foreach( $terms as $term ):
?>                          
    <h3><?php echo $term->name; // Print the term name ?></h3>                          
    <ul>
      <?php                         
          $posts = get_posts(array(
            'post_type' => 'member',
            'taxonomy' => $term->taxonomy,
            'term' => $term->slug,                                  
            'nopaging' => true, // to show all posts in this taxonomy, could also use 'numberposts' => -1 instead
          ));
          foreach($posts as $post): // begin cycle through posts of this taxonmy
            setup_postdata($post); //set up post data for use in the loop (enables the_title(), etc without specifying a post ID)
      ?>        
          <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>    
        <?php endforeach; ?>
    </ul>                                                   
<?php endforeach; ?>
61 pixels
la source
1

Eh bien, c'est un vieux fil, mais si quelqu'un passe comme moi, cela pourrait aider. L'idée est de modifier la requête principale afin que nous n'ayons pas besoin d'aller dans les modèles et de générer de nouvelles requêtes et boucles ...

PS: Encore à tester en gros dbs. C'était satisfaisant dans mon cas.

function grouped_by_taxonomy_main_query( $query ) {

    if ( $query->is_home() && $query->is_main_query() ) { // Run only on the 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, // as you wish...
                'post_type' => 'my_custom_post_type', // If needed... Default is posts
                'fields' => 'ids', // we only want the ids to use later in 'post__in'
                'tax_query' => array( array( 'taxonomy' => $term->taxonomy, 'field' => 'term_id', 'terms' => $term->term_id, )))) // getting posts in the current term
            );
        }

        $query->query_vars['post_type'] = 'my_custom_post_type'; // Again, if needed... Default is posts
        $query->query_vars['posts_per_page'] = 16; // If needed...
        $query->query_vars['post__in'] = $post_ids; // Filtering with the post ids we've obtained above
        $query->query_vars['orderby'] = 'post__in'; // Here we keep the order we generated in the terms loop
        $query->query_vars['ignore_sticky_posts'] = 1; // If you dont want your sticky posts to change the order

    }
}

// Hook my above function to the pre_get_posts action
add_action( 'pre_get_posts', 'grouped_by_taxonomy_main_query' );
Marcelo Viana
la source