Mostrar todas las entradas en un tipo de contenido personalizado, agrupadas por una taxonomía personalizada

4 nov 2011, 14:09:32
Vistas: 64.2K
Votos: 22

Estoy trabajando en una página de miembros donde uso un tipo de contenido personalizado con una taxonomía personalizada. Mi tipo de contenido personalizado se llama member y mi taxonomía personalizada se llama member_groups.

Quiero listar todos los miembros pero agruparlos en sus respectivos grupos.

Para ser claro, tengo 35 miembros divididos en 9 grupos – así que en lugar de hacer la misma consulta nueve veces, quiero hacerla una vez pero agruparlos juntos, de modo que Miembro1, Miembro4 y Miembro11 estén agrupados juntos en un grupo llamado "Marketing".

Estoy usando WP_Query para obtener todas las entradas bajo el tipo de contenido member. He intentado diferentes aproximaciones pero sin resultados exitosos.

¿Cómo puedo lograr esto?

0
Todas las respuestas a la pregunta 7
2
34

Por lo tanto, podrías considerar automatizar las múltiples consultas.

Primero, obtén la lista de términos en tu taxonomía personalizada, usando get_terms():

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

Luego, recorre cada uno, ejecutando una nueva consulta cada vez:

<?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
    // Restablecer cosas, por si acaso
    $member_group_query = null;
    wp_reset_postdata();
}
?>

No veo nada particularmente incorrecto con este enfoque, aunque puede tener una capacidad limitada para escalar (es decir, si tienes cientos o miles de miembros, o términos de member_group, podrías experimentar problemas de rendimiento).

25 ene 2012 16:31:55
Comentarios

Sí, funciona perfectamente. Solo tengo un problema. Quiero mostrar campos personalizados así <?php get_post_meta($member_group_term->ID, 'job_title', true);?> pero no funcionó. También intenté con $post->ID pero tampoco funcionó, ¿podrías ayudarme @Chip Bennett por favor?

Ana DEV Ana DEV
21 dic 2015 09:53:23

Me doy cuenta de que ha pasado más de una década, pero hay algo seriamente incorrecto con este enfoque, ya que estás creando una consulta separada para cada término. Cuando hablamos de un pequeño número de términos, no vamos a ver mucho impacto en el rendimiento. Pero una vez que empezamos a superar los 20-30 términos, este tipo de bucle afectará seriamente los tiempos de carga y el tiempo de respuesta del servidor. Mi sugerencia aquí es realmente obtener todas las publicaciones y luego ejecutar un usort después. De esta manera, no estás saturando la base de datos con un montón de consultas, y obtienes tus resultados en dos pasos.

maiorano84 maiorano84
26 ene 2025 21:58:23
3

Encontré una solución utilizando una consulta personalizada y luego agrupándola con el nombre del término:

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'

Luego, simplemente usando un bucle foreach regular puedo extraer la información que deseo.

Pero todavía estoy interesado en otra forma si existe, tal vez utilizando las propias funciones de WordPress.

4 nov 2011 14:31:36
Comentarios

Acabo de agregar un método alternativo. Tiendo a evitar cualquier cosa que requiera consultas SQL directas.

Chip Bennett Chip Bennett
25 ene 2012 16:32:45

Me alegra ver esto marcado como la respuesta correcta, incluso si la consulta deja de funcionar en WordPress si el esquema cambia en algún momento... El concepto de recopilarlos todos en una sola consulta es la respuesta correcta. La iteración para agrupar las taxonomías en PHP no escalará tan bien como esto.

wowo_999 wowo_999
13 nov 2013 01:03:29

Dios mío, ¿en serio estás escribiendo una consulta directa? Probablemente acabas de entrar al mundo de WP o nunca te has molestado en seguir sus estándares. Esta respuesta no debería ser seleccionada.

pixelngrain pixelngrain
1 jul 2020 10:35:13
0

aún más 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 ));
}

Dentro del array resultante $posts, cada término de taxonomía es la clave para un array anidado que contiene sus posts.

4 abr 2012 16:12:29
0

Tuve exactamente esta necesidad, y la solución de Chip funcionó, excepto por una cosa: se requiere 'field' => 'slug'.

    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() ) {  // aquí va el bucle ?>

También necesitaba que el resultado se mostrara plano, por eso aquí se establece 'get' => 'all'.

Espero que esto ayude a alguien más.

24 ene 2013 03:38:15
0

Tuve que hacer esto en un proyecto hace años. Respuesta similar a djb, pero con un poco más de detalles. Esto generará todos los nombres de tus taxonomías como un h3, con una lista de viñetas de cada título de publicación enlazado a su página de detalle.

<?php // Mostrar todos los nombres de Taxonomías con sus respectivos elementos
$terms = get_terms('member_groups');
foreach( $terms as $term ):
?>                          
    <h3><?php echo $term->name; // Imprimir el nombre del término ?></h3>                          
    <ul>
      <?php                         
          $posts = get_posts(array(
            'post_type' => 'member',
            'taxonomy' => $term->taxonomy,
            'term' => $term->slug,                                  
            'nopaging' => true, // para mostrar todas las publicaciones en esta taxonomía, también se podría usar 'numberposts' => -1
          ));
          foreach($posts as $post): // comenzar ciclo a través de las publicaciones de esta taxonomía
            setup_postdata($post); //configurar datos de la publicación para usar en el bucle (permite usar the_title(), etc sin especificar un ID de publicación)
      ?>        
          <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' => 'miembro', 
      'orderby'   => 'meta_value', 
      'meta_key'  => 'grupo_miembro' 
   ) 
);

Luego, cuando iteres a través de esta consulta, podrías usar un condicional similar a este (en pseudocódigo PHP):

$nombreGrupo = "";
$contador = 0;
if havePosts: while havePosts: thePost

if( $nombreGrupo != post->meta_value )
{
if ($contador > 0)
{
</ul>
}
<h1>Nombre de un grupo</h1>
<ul>
<li>nombre del miembro</li>
}
else
{
<li>nombre del miembro</li>
}

endwhile;endif

</ul>

Espero que esto ayude. Creo que lo estabas haciendo mucho más complicado de lo necesario.

Más información: http://codex.wordpress.org/Class_Reference/WP_Query#Taxonomy_Parameters

5 nov 2011 07:01:14
0

Bueno, es un hilo antiguo, pero si alguien pasa por aquí como yo lo hice, esto podría ayudar. La idea es modificar la consulta principal para que no necesitemos ir a las plantillas y generar nuevas consultas y bucles...

PD: Aún no se ha probado en bases de datos grandes. Fue satisfactorio en mi caso.

function grouped_by_taxonomy_main_query( $query ) {

    if ( $query->is_home() && $query->is_main_query() ) { // Ejecutar solo en la página de inicio

        $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, // como desees...
                'post_type' => 'my_custom_post_type', // Si es necesario... Por defecto son posts
                'fields' => 'ids', // solo queremos los IDs para usar luego en 'post__in'
                'tax_query' => array( array( 'taxonomy' => $term->taxonomy, 'field' => 'term_id', 'terms' => $term->term_id, )))) // obteniendo posts en el término actual
            );
        }

        $query->query_vars['post_type'] = 'my_custom_post_type'; // Nuevamente, si es necesario... Por defecto son posts
        $query->query_vars['posts_per_page'] = 16; // Si es necesario...
        $query->query_vars['post__in'] = $post_ids; // Filtrando con los IDs de posts que obtuvimos arriba
        $query->query_vars['orderby'] = 'post__in'; // Aquí mantenemos el orden que generamos en el bucle de términos
        $query->query_vars['ignore_sticky_posts'] = 1; // Si no quieres que tus posts fijos cambien el orden

    }
}

// Enganchar mi función anterior a la acción pre_get_posts
add_action( 'pre_get_posts', 'grouped_by_taxonomy_main_query' );
22 abr 2017 09:33:04