¿Es posible ordenar por taxonomía usando wp_query?

8 abr 2011, 18:44:50
Vistas: 91.6K
Votos: 62

Mi pregunta es sencilla, estoy usando WP_Query para recuperar algunos posts de tipo personalizado filtrando por una taxonomía usando tax_query.

Ahora mi problema es que me gustaría ordenar los resultados por la taxonomía, pero según la documentación y buscando en la web no encuentro una solución.

El parámetro orderby en WP_Query te permite ordenar por muchos campos, incluso campos meta personalizados, pero parece que no soporta taxonomías.

¿Alguna indicación en la dirección correcta?

Gracias a todos.

0
Todas las respuestas a la pregunta 13
7
72

La respuesta aceptada para esta pregunta es inaceptable. No es lógico asumir que ordenar por taxonomía "no tiene sentido". La respuesta que dio no tiene sentido.

Considera tener un tipo de publicación "menú". Luego tienes una taxonomía personalizada "FoodCategories" (Categorías de Comida). La taxonomía FoodCategories tiene los términos "Breakfast" (Desayuno), "Lunch" (Almuerzo) y "Dinner" (Cena). Si realizas una consulta utilizando el parámetro tax_query, obtendrás un conjunto de resultados con todos los términos, pero ordenados por fecha de publicación.

Para obtener el orden correcto de estas publicaciones en relación a sus términos, y luego mostrarlas en el front-end agrupadas apropiadamente por sus categorías, tienes que recorrer el conjunto de resultados, consultar cada publicación individual para encontrar sus términos, compararlos con el término actual, filtrarlos en un array y continuar este proceso. Luego tienes que volver a recorrer el nuevo array para mostrarlo. Esto no es productivo.

Sería bueno si WordPress tuviera una opción "tax__in" para orderby como tiene "post__in", pero como no la tiene, tienes que hacer el ridículo proceso mencionado anteriormente; personalizar la consulta manualmente usando los filtros 'posts_orderby' y 'posts_join' para ajustar el método de ordenación y añadir el término al conjunto de resultados, respectivamente; o hacer una nueva consulta para cada término que estés filtrando dentro de las secciones HTML correspondientes a esos términos.

Lo más eficiente sería modificar la cadena de consulta usando filtros. Lo más fácil sería hacer tres consultas separadas. La API de WordPress debería manejar el ordenamiento por taxonomía, o cualquier parámetro de consulta restrictivo. Si estás restringiendo una consulta basada en ciertas condiciones, hay una alta probabilidad de que muchos necesiten ordenar por esas mismas condiciones.

28 jul 2014 14:36:51
Comentarios

Lo siento, pero estás equivocado. Ordenar por taxonomía no tiene sentido en tu caso tampoco. ¿Qué quieres mostrar? ¿Todos los Desayunos primero, seguidos de todas las Cenas, luego todos los Almuerzos? Deberías seleccionar lo que quieres y el orden en que lo quieres, pero la taxonomía es solo una etiqueta de agrupación. No son "datos" significativos por los que deberías ordenar. Si lo son, entonces no debería ser un término en una taxonomía, deberías convertirlo en un post-meta.

Otto Otto
20 oct 2014 14:57:21

Vamos, claro que habrá casos en los que querrás ordenar posts por términos de taxonomía. Otro ejemplo es un tipo de post Película con una taxonomía de Clasificación. En una lista de películas, es fácil imaginar que la gente quiera ordenar una lista de películas por clasificación para que todas las películas con clasificación G, luego PG, etc. aparezcan al principio. (En este y el ejemplo de comidas podrían ordenarse por term_id en lugar de name.) Hay una gran área gris de casos donde probablemente sea mejor usar una taxonomía y no meta, pero también sería útil que esa taxonomía se pueda ordenar.

SeventhSteel SeventhSteel
10 mar 2015 22:51:49

Las clasificaciones PG, G y similares son una buena elección de taxonomía, excepto que son datos sobre películas específicas. Por lo tanto, son meta. Son datos, no categorías. El simple hecho de tener un número limitado de opciones no convierte algo en taxonomía. Si necesita ordenarse, entonces conviértelo en meta o fuerza el orden mediante código específico de taxonomía. Por cierto, NC17 va después de PG. Así que necesitarás código para hacer ese ordenamiento de todas formas.

Otto Otto
10 nov 2015 03:05:34

Sé que llego tarde a la fiesta con este comentario, pero acabo de toparme con esto. Ordenar por taxonomía puede tener sentido en algunas situaciones. Tenemos listados de trabajos en un proyecto como un tipo de publicación y luego Estado y Ciudad donde está el trabajo como taxonomías. Queremos que sean fácilmente agrupables (mostrar todos los trabajos en un estado o mostrar todos los trabajos en una ciudad), así que la taxonomía fue la mejor solución. Al mismo tiempo, hay una búsqueda general de trabajos donde queremos ordenarlos primero por título, luego por estado y luego por ciudad.

Dennis Puzak Dennis Puzak
23 oct 2018 13:39:32

Otro caso de uso: Un cliente tiene varios artículos, cada uno con una categoría. El cliente quiere que haya una página que liste todos los artículos, que se puedan ordenar alfabéticamente, por fecha o por categoría. Las categorías también se pueden filtrar, pero listar todos los artículos por categoría en orden alfabético no es un caso de uso tan descabellado y lo ves aparecer bastante a menudo.

W Biggs W Biggs
6 jun 2019 19:06:27

Otro caso de uso aquí: tenemos varios 'clientes' en un tipo de publicación personalizado, y hay una taxonomía de región que nos permite indicar dónde cada cliente realiza su negocio. Nos han pedido que agreguemos funcionalidad para que cuando un visitante vea la lista de clientes, los vea ordenados por región, con los clientes cercanos a ellos primero.

Matt Keys Matt Keys
2 oct 2020 22:21:23

Otto tiene razón en que si estás intentando hacer esto, debes revisar tu estructura de datos; nueve de cada diez veces está mal. SIN EMBARGO, insistir dogmáticamente en que "todos los demás están equivocados" simplemente no es inteligente. Este es mi caso de uso: Los apellidos deben ordenarse por la primera letra en mayúscula; de Courcy va bajo C y De Haan bajo D. Es fácil crear una taxonomía personalizada con regex que ordene estos correctamente; sin embargo, ahora mostrar todas mis personas con una consulta simple (a través de 'meta_key' => 'alphabet') no es posible. Tengo que duplicar mi código y definir mi propio filtro 'orderby' => 'quasi_alphabetic_by_title'.

user3445853 user3445853
20 ene 2023 14:24:43
Mostrar los 2 comentarios restantes
6
19

Sí, pero es bastante complejo...

Añade esto al functions.php de tu tema:

function orderby_tax_clauses( $clauses, $wp_query ) {
    global $wpdb;
    $taxonomies = get_taxonomies();
    foreach ($taxonomies as $taxonomy) {
        if ( isset( $wp_query->query['orderby'] ) && $taxonomy == $wp_query->query['orderby'] ) {
            $clauses['join'] .=<<<SQL
LEFT OUTER JOIN {$wpdb->term_relationships} ON {$wpdb->posts}.ID={$wpdb->term_relationships}.object_id
LEFT OUTER JOIN {$wpdb->term_taxonomy} USING (term_taxonomy_id)
LEFT OUTER JOIN {$wpdb->terms} USING (term_id)
SQL;
            $clauses['where'] .= " AND (taxonomy = '{$taxonomy}' OR taxonomy IS NULL)";
            $clauses['groupby'] = "object_id";
            $clauses['orderby'] = "GROUP_CONCAT({$wpdb->terms}.name ORDER BY name ASC) ";
            $clauses['orderby'] .= ( 'ASC' == strtoupper( $wp_query->get('order') ) ) ? 'ASC' : 'DESC';
        }
    }
    return $clauses;
}

    add_filter('posts_clauses', 'orderby_tax_clauses', 10, 2 );

Esto es una combinación de código encontrado y cosas que hice yo mismo. Explicarlo es bastante difícil, pero en resumen, con esto funcionando, puedes poner ?orderby=(taxonomia)&order=ASC (o DESC) y ¡funcionará perfectamente!

8 abr 2011 19:36:19
Comentarios

Gracias Drew, voy a intentar ejecutar ese SQL, necesito editarlo un poco, pero podría funcionar. Mi único problema ahora es que podría estar yendo en la dirección equivocada como señaló Otto. Gracias Drew. EDIT- No necesito editar, ya puedo ver dónde necesita ajustes :) Gracias

yeope yeope
8 abr 2011 19:45:12

Si lo copiaste en los últimos dos minutos, no funcionará, vuelve a copiarlo ahora, lo arreglé. Estaba configurado para dos taxonomías específicas, mejoré el código para que funcione con todas las taxonomías registradas.

Drew Gourley Drew Gourley
8 abr 2011 19:48:14

Gracias de nuevo. Por si acaso probé tu solución y funciona más o menos. También, si alguien más quiere usarlo, necesitas cambiar add_filter('posts_clauses', 'orderby_tax_clauses', 10, 2 ); por add_filter('posts_clauses', 'todo_tax_clauses', 10, 2 ); Gracias :)

yeope yeope
9 abr 2011 01:29:02

Sí, esto ya está corregido en el bloque de código, lo tomé de un proyecto en el que estoy trabajando y olvidé cambiar el nombre de la función aunque lo cambié en el hook.

Drew Gourley Drew Gourley
9 abr 2011 09:39:39

¿Sabes si es posible ordenar las taxonomías por ID en lugar de por nombre? Estoy intentando obtener el mismo resultado ordenando los grupos de taxonomías por ID

Javier Villanueva Javier Villanueva
17 jul 2013 01:43:36

Envolví esto en un if (is_admin) {} para evitar que esté disponible en otros lugares...

stephendwolff stephendwolff
25 mar 2022 17:56:09
Mostrar los 1 comentarios restantes
14
16

No, no es posible ordenar por taxonomía, porque desde cierto punto de vista, eso en realidad no tiene mucho sentido.

Las taxonomías son formas de agrupar cosas. Así que el propósito de tener una taxonomía en las publicaciones sería realmente tener términos en esa taxonomía que sean compartidos entre las publicaciones. Si una taxonomía tuviera términos que solo se usaran en una publicación cada uno, entonces eso haría que la taxonomía careciera de sentido. Y si los términos se compartieran como deberían ser, entonces ordenar por ellos no produciría nada particularmente útil.

Lo que deberías usar en tal situación son los metadatos de la publicación. Puedes ordenar por metadatos de publicación, y son únicos para cada publicación.

Edición: Dicho esto, puedes ordenar por taxonomía haciendo una consulta SQL personalizada usando un filtro, simplemente no puedes hacerlo desde un WP_Query sin modificar: http://scribu.net/wordpress/sortable-taxonomy-columns.html

Sin embargo, si tienes que recurrir a hacer este tipo de cosas, entonces tu estructura de diseño de datos está mal desde el principio. Los "términos" en la taxonomía no son "datos" reales. Los términos en sí mismos no tienen un significado inherente, solo son etiquetas para la agrupación particular que describen. Si los estás tratando como datos significativos, entonces tienes un error de diseño subyacente.

Las taxonomías agrupan cosas asignándoles términos. Esa agrupación es el propósito principal de las taxonomías, los términos son solo caras bonitas en la agrupación. Si tienes metadatos significativos para asignar a una publicación, entonces deberías usar los metadatos de la publicación para ello. Y eso puedes ordenar, porque los metadatos de publicación usan tanto claves como valores para almacenar información. Con una taxonomía, en realidad solo estás almacenando claves, siendo sus valores las publicaciones agrupadas por ese término.

Las cosas son más fáciles a largo plazo si usas el enfoque correcto. Aunque no estoy diciendo que no puedas hacer algo extraño con la taxonomía, solo te estás complicando las cosas a largo plazo usándola incorrectamente.

8 abr 2011 19:20:29
Comentarios

Hola Otto, gracias por la respuesta. Entiendo tu punto y tal vez esté tomando el camino equivocado con esto. En mi ejemplo de un sitio de series de TV, tengo una taxonomía para serie 1, serie 2, serie 3, etc. Así puedo agrupar todos los diferentes programas de TV por número de serie. Luego tengo lo mismo para los episodios, Episodio 01, Episodio 02, etc. Lo que me gustaría es que al mostrar una lista de todos los episodios, estos se ordenen por episodio y serie. Analizaré entonces los metadatos y campos personalizados. Gracias Otto.

yeope yeope
8 abr 2011 19:35:58

@yeope tu taxonomía debería ser "series" y tus términos deberían ser serie 1, serie 2, etc. Con los episodios, asumo que una serie contiene múltiples episodios, por lo que podría usar la misma taxonomía "series" y si son jerárquicos, entonces episodio 1, episodio 2, etc. tendrían el término padre "serie x". Luego podrías consultar una serie completa en orden con los episodios apareciendo donde deberían.

Chris_O Chris_O
8 abr 2011 22:17:02

@Chris_O Entiendo, ¡puede que tengas razón ahí! El único problema que veo es el hecho de tener que repetir los términos "Episodio 1", "Episodio 2" para cada serie. También no poder agrupar todos los episodios 1 independientemente de la serie, pero creo que probablemente haya una solución. Gracias Chris_O

yeope yeope
9 abr 2011 01:26:19

Usar una taxonomía para episodios en realidad no tiene mucho sentido, porque la agrupación no sirve. Piensa en esto: si tienes "episodio 1" como término, entonces estás agrupando el episodio 1 con todos los demás episodios 1 de cualquier otro programa de TV. Los números de episodio y serie tienen más sentido como post_meta, porque son específicos para ese programa en particular y no son útiles como grupo. El nombre del programa de TV sería útil como término en una taxonomía de tv-show, porque así agrupas todo el programa junto.

Otto Otto
15 abr 2011 22:28:37

Pero una taxonomía para series medio funciona, pero solo porque agrupa los programas en una temporada o algo similar, aunque tendrías que consultarla junto con la taxonomía tv-show. En dicha taxonomía de series, tus términos serían 1, 2, 3, que representan el número de temporada del programa. Pero aun así preferirías esta información como postmeta, ya que querrás ordenar por ella. Y como también puedes consultar postmeta, no tiene mucho sentido duplicarla como taxonomía.

Otto Otto
15 abr 2011 22:31:30

@Otto, al final terminé usando campos personalizados :) Tenía más sentido.

yeope yeope
4 may 2011 21:01:59

Otto siguió esto con una interesante publicación en el blog: Cuándo (no) usar una Taxonomía Personalizada.

Jan Fabry Jan Fabry
5 may 2011 09:55:59

@otto Gracias por compartir esto, es realmente bueno leer un poco más sobre taxonomías y sus usos. Específicamente estoy interesado en conocer tus pensamientos sobre una situación como la descrita en la publicación Columnas de Taxonomía Ordenables. ¿Cuál sería la mejor solución cuando quiero poder consultar todas las publicaciones en un rango de colores, pero también quiero ordenar por color? Tal vez esto sería mejor como una pregunta separada...

Gaffen Gaffen
20 dic 2013 22:54:54

Si quieres ordenar por ello, entonces realmente debería ser meta en lugar de una taxonomía. Ordenar por taxonomía no tiene mucho sentido, en realidad.

Otto Otto
21 dic 2013 09:42:43

Gracias @Otto. Aunque no estoy de acuerdo con tu afirmación: "Sin embargo, si tienes que recurrir a hacer este tipo de cosas, entonces tu estructura de diseño de datos está mal desde el principio"... Podría ser útil poder reordenar la lista de entradas por término de categoría en el lado del administrador...

ClemC ClemC
23 may 2017 16:14:47

@ClemC Eso no tiene mucho sentido. Las entradas pueden tener múltiples categorías. ¿Por qué criterio estás ordenando? ¿Cuál es tu criterio de ordenación secundario cuando dos entradas tienen la misma categoría? Ese es el tipo de problema con el que te encuentras, las taxonomías son solo agrupaciones, el "término" es solo una cara bonita de esa agrupación, no es la parte importante. La parte importante es el grupo en sí. No ordenarías nombres de animales alfabéticamente por su taxonomía linneana. No te ayuda en nada.

Otto Otto
25 may 2017 00:37:37

Hola @Otto, tienes razón. Tomé como referencia el caso de mi proyecto actual que es bastante particular... Un CPT (película) que permite solo un único término de una taxonomía personalizada (festival) con botones de radio para su selección. El orden predeterminado de la lista de CPT es por término (festival) que en este caso particular tiene suficiente lógica, ¿no? No se me ocurre un mejor enfoque sobre el "diseño de datos"... He implementado "festivales" como una taxonomía porque los únicos datos que necesitan son su descripción y agrupa lógicamente "películas". PD: Perdón por mi inglés.

ClemC ClemC
25 may 2017 11:10:46

Sí, es justo, pero entonces es un grupo. Estás agrupando cosas juntas. ¿Qué significa "ordenar por" en ese contexto? Si tienes un montón de cosas en el mismo grupo, entonces puedes "seleccionar por" ese grupo, y eso tiene sentido, pero "ordenar" es algo totalmente diferente. Ordenas por campos que tienen valores diferentes, no por campos que tienen todos los mismos valores.

Otto Otto
25 may 2017 11:36:37

Lo siento @Otto, solo ahora noto tu respuesta... Estoy totalmente de acuerdo con tus puntos semánticos y lógica. Pero en mi contexto, "ordenar por" sería principalmente una cuestión ergonómica. Agrupar visualmente las proyecciones por "festival" puede ayudar importante al usuario a obtener un resumen visual basado en el factor más importante para él, esto de un vistazo. Por lo tanto, no estoy seguro de poder lograr esto de otra manera que no sea "ordenando", lo cual reconozco que no es un término apropiado...

ClemC ClemC
19 ago 2017 22:26:55
Mostrar los 9 comentarios restantes
5
13

Llego un poco tarde a esto, pero hay una forma más simple y más al estilo WordPress de hacerlo.

Construye tu tax_query como de costumbre.

$tax_query = array();
$tax_query['relation']="OR";
$tax_query[] = array(
    'taxonomy' => 'product_cat', // Taxonomía de categoría de producto
    'field'    => 'slug',        // Campo a usar (slug)
    'terms'    => $cat_terms,    // Términos a incluir
);
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1; // Página actual

Configura tus argumentos para query_posts o WP_Query

$args = array(
    'post_type'=>'post',          // Tipo de post
    'posts_per_page'=>12,        // Posts por página
    'paged'=>$paged,             // Paginación
    'tax_query' => $tax_query,   // Query de taxonomía
);

Antes de hacer tu llamada query_posts / WP_Query, engancha el filtro orderby y sobrescríbelo

add_filter('posts_orderby', 'edit_posts_orderby');
function edit_posts_orderby($orderby_statement) {
    $orderby_statement = " term_taxonomy_id ASC "; // Ordenar por ID de taxonomía ascendente
    return $orderby_statement;
}
query_posts($args);
remove_filter('posts_orderby', 'edit_posts_orderby'); // No olvides remover el filtro después

No olvides remover el filtro después...

Esto funciona porque tax_query crea los joins necesarios, solo necesitas ordenar por uno de los campos del join.

31 oct 2014 15:48:14
Comentarios

¿Alguna idea sobre cómo ordenar por nombre en lugar de term_taxonomy_id? Cambiar term_taxonomy_id en orderby_statement genera errores

tehlivi tehlivi
5 oct 2016 00:52:51

¡Esta es la respuesta correcta para cualquiera que esté interesado!

Mayra M Mayra M
21 jun 2018 13:43:17

@tehlivi este método no funciona para ordenar por nombre porque el nombre está en la tabla wp_terms. WordPress parece almacenar en caché los términos de taxonomía, así que incluso si tu consulta de taxonomía busca por slug o nombre, que también están en la tabla wp_terms, WordPress los procesa a través de su lista en caché y los intercambia por IDs almacenados en term_relationships.term_taxonomy_id, por lo que no tiene que consultar la tabla wp_terms como parte de la consulta principal. Lo que significa que ni el nombre ni el slug están incluidos en la consulta SQL resultante. Tienes que añadir joins.

Ethan C Ethan C
25 oct 2021 23:34:35

@EthanC oye hombre, gracias por tu respuesta detallada, y espero que si alguien encuentra esto en el futuro, encuentre útil tu respuesta. Pero para mí, ciertamente es difícil recordar algo de 2016. creo que terminé pasando el array por una función de ordenación después de que la consulta se completara. Estoy seguro de que cualquier desarrollador que tomó ese proyecto después de que dejé la compañía me odia. Ja.

tehlivi tehlivi
27 oct 2021 00:17:06

@tehlivi Sí, terminé ignorando la consulta principal por completo en caso de que algunos posts tuvieran asignados más de un término. Opté en su lugar por ejecutar get_terms() y luego get_posts para cada término. Añadió ~15 consultas a la carga de la página, pero le dio al diseñador el resultado que quería.

Ethan C Ethan C
28 oct 2021 02:03:53
4

No estoy seguro de por qué todas las soluciones aquí son exageradas. OK, fue hace medio siglo, pero actualmente estoy ejecutando el siguiente código y funciona:

   <?php // Por defecto
    $wheels_args = array(
        'post_type' => 'wheels',
        'posts_per_page' => '96',
        'orderby' => 'taxonomy, name', // Solo ingresa 2 parámetros aquí, separados por coma
        'order'=>'ASC'
    );
    $loop = new WP_Query($wheels_args);
    ?>

Esto ordenará las taxonomías de tu CPT primero por su taxonomía en orden alfabético y dentro de estos grupos de taxonomía también por orden alfabético.

6 jul 2017 15:26:34
Comentarios

@yeope ¿Por qué esta es la respuesta aceptada? Gracias a Dios que seguí bajando

Juan Solano Juan Solano
22 oct 2019 02:17:52

No pude hacer que esto funcione. ¿Puedes señalar un sitio con alguna explicación sobre eso? no hay nada aquí, que respalde tu código

honk31 honk31
9 abr 2020 20:15:41

No se analiza correctamente, especialmente con esta coma, y es ignorado por WP (6.x).

Picard Picard
2 sept 2022 17:05:44

Esto funcionó para mí, wp 6.5.4. Debes ajustar el valor después de la coma, por ejemplo, si tu taxonomía fuera post_tag literalmente escribirías 'orderby' => 'taxonomy, post_tag',.

Tomas Mulder Tomas Mulder
24 jun 2024 19:21:12
1

Bueno, me gustaría compartir mi experiencia ordenando tipos de contenido personalizados (custom post types) por categoría/taxonomía.

EL SITIO WEB

  1. Un sitio web de una agencia de viajes basado en WordPress
  2. Contenido principal en un tipo de contenido personalizado llamado 'ruta'
  3. Taxonomía con esta estructura: Tipo-de-viaje > continente > país

EL CASO

En las páginas de archivo de categorías, el cliente quería que las publicaciones se ordenaran:

  1. Por continente, ordenados por número de rutas en cada uno.
  2. Por país, ordenados alfabéticamente.

LOS PASOS

Primero, capturé la consulta de la página de archivo sin modificar, que resultó ser así:

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID 
FROM wp_posts 
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) 
WHERE 1=1 
AND ( wp_term_relationships.term_taxonomy_id IN (5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,22,23,25,26,28,29,31,32,33,35,38,95,101,102,193) )
AND wp_posts.post_type IN ('ruta', 'nav_menu_item') 
AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 45 
AND wp_posts.post_status = 'private') 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.post_date DESC LIMIT 0, 20

Segundo, modifiqué el código SQL en Sequel Pro contra la base de datos para adaptarlo a mis necesidades. Obtuve esto (sí, probablemente se puede mejorar: mi conocimiento de MySQL no es excelente):

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID, tt1.parent AS pare,
    (
    SELECT COUNT(*) 
    FROM  wp_posts
    INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
    INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id = wp_term_relationships.term_taxonomy_id )
    INNER JOIN wp_term_taxonomy AS tt2 ON ( tt2.term_taxonomy_id = tt1.term_taxonomy_id )
    WHERE 1=1  
    AND tt1.parent = pare
    ) AS Total
FROM  wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id = wp_term_relationships.term_taxonomy_id )
INNER JOIN wp_terms ON ( tt1.term_id = wp_terms.term_id )
WHERE 1=1  
AND ( wp_term_relationships.term_taxonomy_id IN (5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,22,23,25,26,28,29,31,32,33,35,38,95,101,102,193) ) 
AND wp_posts.post_type IN ('ruta', 'nav_menu_item') 
AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 45 
AND wp_posts.post_status = 'private') 
GROUP BY wp_posts.ID 
ORDER BY
total DESC,
wp_terms.name  

Tercero, enganché la consulta en el archivo functions.php con tres filtros: posts_fields, posts_join y posts_orderby

El código en functions.php:

function xc_query_fields( $fields ) {

   $fields = "wp_posts.ID, wp_posts.post_title, wp_terms.name, tt1.parent AS pare,
    (
    SELECT COUNT(*) 
    FROM  wp_posts
    INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
    INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id = wp_term_relationships.term_taxonomy_id )
    INNER JOIN wp_term_taxonomy AS tt2 ON ( tt2.term_taxonomy_id = tt1.term_taxonomy_id )
    WHERE 1=1  
    AND tt1.parent = pare
    )
    AS Total";
     return $fields;
}


function xc_query_joins( $join ) {
$join .= "INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
   INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id = wp_term_relationships.term_taxonomy_id )
   INNER JOIN wp_terms ON ( tt1.term_id = wp_terms.term_id )";
 return $join;
}


function xc_query_orderby( $join ) {
    $join = "total DESC, wp_terms.name ";
    return $join;
 }

Finalmente activé los filtros desde el hook pre_get_post según algunas condiciones

function filtra_queries( $query )
{

  if (  is_archive()  && $query->is_main_query() && !is_admin()  ) {

$rutes = array('viajes-privados', 'asia', 'africa', 'oceania', 'america', 'oriente-proximo');

if  ( in_array( $query->get('category_name'), $rutes ) ) 
  {
  add_filter( 'posts_fields', 'xc_query_fields' );
  add_filter( 'posts_join', 'xc_query_joins' );
  add_filter( 'posts_orderby', 'xc_query_orderby' );
}// end if in_array

  }// end if is_archive

}
 add_filter('pre_get_posts', 'filtra_queries');

Espero que esto pueda ayudar a alguien

4 ene 2015 17:09:00
Comentarios

Buen trabajo, es ridículo que se necesite esta cantidad de código para ordenar algo por una taxonomía. Un gran problema con WP.

serraosays serraosays
21 jul 2017 02:27:03
0

Tuve un problema muy similar al que enfrenté: quiero ordenar un archivo de tipo de publicación personalizada (artículos de revista) por una taxonomía personalizada (números). Nunca hago consultas SQL directas en mi sitio - y usualmente si estás como estas otras respuestas - necesitas reconsiderar tu enfoque.

PROBLEMAS:

1) WordPress no te permite ordenar taxonomías de manera inteligente.

2) WordPress simplemente no permite que orderby use taxonomías en WP_Query para tipos de publicación (como lo explica Otto).

SOLUCIONES:

1) Ordenar taxonomías se logra mejor actualmente con el plugin Custom Taxonomy Order NE. Te permite ordenar la taxonomía mediante un editor WYSIWYG en wp-admin, lo cual no es como yo lo haría pero no he encontrado nada mejor.

Cuando configures el plugin, obtendrás algo similar a lo que he hecho aquí. Toma nota de la opción Auto-sort Queries of this Taxonomy - configúrala como Custom Order as Defined Above; esto te dará el orden que necesitas. Captura de pantalla:

Visualización de Custom Taxonomy Order NE

2) Con una taxonomía ordenada en su lugar, ahora puedes crear una serie de llamadas WP_Query que recorran cada término, creando efectivamente un archivo ordenado por la taxonomía. Usa get_terms() para crear un array de todos los términos de la taxonomía, luego ejecuta un foreach sobre cada término. Esto crea un WP_Query para cada término que devolverá todas las publicaciones para un término dado, creando efectivamente un archivo ordenado por término de taxonomía. Código para hacer que esto ocurra:

  // Obtén tus términos y ponlos en un array
  $issue_terms = get_terms([
    'taxonomy' => 'issues',
    'hide_empty' => false,
  ]);

  // Ejecuta foreach sobre cada término para configurar la consulta y mostrar las publicaciones
  foreach ($issue_terms as $issue_term) {
    $the_query = new WP_Query( array(
      'post_type' => 'post',
      'tax_query' => array(
        array(
          'taxonomy' => 'issues',
          'field' => 'slug',
          'terms' => array( $issue_term->slug ),
          'operator' => 'IN'
        )
      )
    ) );

    // Ejecuta el loop sobre cada consulta
    while($the_query->have_posts()) :
      $the_query->the_post();

      // TU SALIDA DE PLANTILLA PARA CADA PUBLICACIÓN

    endwhile;
  }

Lectura relacionada en este sitio: Mostrar todas las publicaciones en un tipo de publicación personalizada, agrupadas por una taxonomía personalizada

10 abr 2017 17:45:43
0

Aquí está la solución que he utilizado para este problema en particular. Esta solución es para casos extremos donde no es posible usar un filtro pre_get_posts y ya existe una paginación en la consulta (por ejemplo: WooCommerce):

global $wpdb;

$taxonomies = array('my-tax-1', 'my-tax-2', 'my-tax-3');

$orderby = "'".implode("', '", array_keys($taxonomies))."'";
$id_sql = $GLOBALS['wp_query']->request;

$id_sql = preg_replace('/LIMIT\s+\d+\s?,?\s\d*/', '', $id_sql);
$id_sql = str_replace('SQL_CALC_FOUND_ROWS', '', $id_sql);

$term_sql = "SELECT
  tt.taxonomy AS `taxonomy`,
  t.name AS `term_name`,
  t.slug AS `term_slug`,
  count(*) AS `term_count`
FROM ({$id_sql}) p 
JOIN wp_term_relationships tr
  ON p.ID = tr.object_id
JOIN wp_term_taxonomy tt
  ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms t
  ON tt.term_id = t.term_id
WHERE tt.taxonomy IN ({$orderby})
GROUP BY t.slug
ORDER BY
  FIELD(tt.taxonomy, {$orderby})"; // Añade aquí un ordenamiento más específico si es necesario

$results = $wpdb->get_results($term_sql, ARRAY_A);

He utilizado esto para crear un menú de navegación ordenado por taxonomía, término y conteo de publicaciones por término.

Si solo quieres las publicaciones, cambia la consulta a SELECT p.* y GROUP BY p.ID

24 mar 2017 18:48:47
3

Me gusta ordenar mis términos manualmente, así que uso un plugin para hacerlo. Y soy fan del filtro pre_get_posts, así que tomé el ejemplo funcional de Drew Gourley y lo adapté para que funcione con eso. Este es un caso algo especial, pero lo comparto por si ayuda a alguien. El siguiente código va en functions.php o en un plugin personalizado.

Primero comencemos con el filtro. Ordenamos el tipo de publicación personalizado music por la taxonomía personalizada style:

function so14306_pre_get_posts($query)
{
    if (is_admin()) :
        return;
    endif;

    if ($query->is_main_query()) :
        if (is_post_type_archive('music')) :
            $query->set('orderby', 'style');
        endif;
    endif;
}

add_action('pre_get_posts', 'so14306_pre_get_posts');

Luego llamamos al filtro post_clauses:

function so14306_posts_clauses($clauses, $wp_query)
{
    global $wpdb;

    if (isset($wp_query->query_vars['orderby']) && $wp_query->query_vars['orderby'] === 'style') {
        $orderby = $wp_query->query_vars['orderby'];
        $clauses['join'] .= <<<SQL
LEFT OUTER JOIN {$wpdb->term_relationships} ON {$wpdb->posts}.ID={$wpdb->term_relationships}.object_id
LEFT OUTER JOIN {$wpdb->term_taxonomy} USING (term_taxonomy_id)
LEFT OUTER JOIN {$wpdb->terms} USING (term_id)
SQL;
        $clauses['where'] .= " AND (taxonomy = '{$orderby}' OR taxonomy IS NULL)";
        $clauses['groupby'] = "object_id";
        $clauses['orderby'] = "GROUP_CONCAT({$wpdb->terms}.term_order ORDER BY {$wpdb->terms}.term_order ASC) ASC";
        $clauses['orderby'] .= ", {$wpdb->posts}.post_name ASC";
    }

    return $clauses;
}

add_filter('posts_clauses', 'so14306_posts_clauses', 10, 2);

Ahora todo lo que necesitas hacer es ordenar tus taxonomías con el siguiente plugin: Simple Custom Post Order. Este plugin es obligatorio para esta solución, ya que añade la columna term_order a la base de datos.

Y esta línea: $clauses['orderby'] .= ", {$wpdb->posts}.post_name ASC" ordena las publicaciones por título, así que el ordenamiento completo de la solución anterior es: término de taxonomía => título de publicación.

9 abr 2020 19:33:04
Comentarios

Muchas gracias, esto es muy útil. Es genial tener una forma de ordenar visualmente. ¿Sabes por qué está la parte "OR taxonomy IS NULL"? Parece algo que no es necesario.

Jordan Carter Jordan Carter
6 oct 2021 22:14:27

Muestra el primer término correctamente, pero después de esas publicaciones el siguiente término no sigue lógicamente el orden del menú como está establecido con SCP Order. Me pregunto si es porque estoy intentando hacerlo con productos, y WooCommerce ya tiene un orden de atributos...quizás los dos están en conflicto. En la base de datos, sin embargo, los IDs en la columna term_order son correctos...

Jordan Carter Jordan Carter
6 oct 2021 22:32:44

Cambiar la línea de orderby de GROUP_CONCAT a lo siguiente parece ayudar: $clauses['orderby'] = "{$wpdb->terms}.term_order ASC";

Jordan Carter Jordan Carter
6 oct 2021 22:44:09
1

Una forma bastante sencilla de hacer esto es agregar una función que:

  1. Cuando tu publicación sea publicada...
  2. Obtener el ID/slug/etc de tu categoría...
  3. Guardarlo como un valor meta personalizado para tu publicación

Y luego, en tu loop, ordenar tus publicaciones por ese valor meta.

Entonces:

// 1
add_action( 'publish_post', 'save_and_add_meta' );

function save_and_add_meta($post_id){

        //Eliminar temporalmente la acción para evitar un bucle infinito
        remove_action( 'publish_post', 'save_and_add_meta' );

        // 2            
        $category_slug = get_the_terms($post_id, 'your_taxonomys_name')[0]->slug;

        //3
        add_post_meta($post_id, 'cat_slug', $category_slug);

        //Agregar la acción nuevamente
        add_action( 'publish_post', 'save_and_add_meta' );
}

Luego en tu consulta de WP agrega en tus $args:

'meta_key' => 'cat_slug',
'orderby' => 'meta_value',
'order' => 'DESC',

Esto funciona si puedes encontrar una manera de restringir a los usuarios a asignar solo una categoría por publicación, o si tus categorías son mutuamente excluyentes. Si asignan más de una categoría, sin embargo, la publicación se dejaría fuera de una de ellas.

11 sept 2020 18:56:41
Comentarios

Estoy pensando lo mismo, aunque duplica los datos.

Sisir Sisir
22 sept 2021 23:18:54
1

Es como una consulta antes de la consulta, pero no molestará si no estamos consultando demasiadas publicaciones... La idea es modificar la consulta principal para que ni siquiera necesitemos ir a las plantillas y generar nuevas consultas y bucles...

function grouped_by_taxonomy_main_query( $query ) {

    if ( $query->is_home() && $query->is_main_query() ) { // Solo se ejecuta 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 entradas
                'fields' => 'ids', // solo queremos los IDs para usarlos luego en 'post__in'
                'tax_query' => array( array( 'taxonomy' => $term->taxonomy, 'field' => 'term_id', 'terms' => $term->term_id, )))) // obteniendo publicaciones en el término actual
            );
        }

        $query->query_vars['post_type'] = 'my_custom_post_type'; // Nuevamente, si es necesario... Por defecto son entradas
        $query->query_vars['posts_per_page'] = 16; // Si es necesario...
        $query->query_vars['post__in'] = $post_ids; // Filtramos con los IDs de publicaciones obtenidos anteriormente
        $query->query_vars['orderby'] = 'post__in'; // Aquí mantenemos el orden generado en el bucle de términos
        $query->query_vars['ignore_sticky_posts'] = 1; // Si no quieres que tus publicaciones fijas cambien el orden

    }
}

// Engancho 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:38:39
Comentarios

Esto fallará, no puedes usar get_posts o WP_Query dentro de pre_get_posts, creará un bucle infinito. Porque cuando usas get_posts o WP_Query, se activará el hook pre_get_posts y esto causará un bucle infinito, incluso si verificas is_main_query, no se detendrá y seguirá ejecutándose continuamente.

Den Pat Den Pat
23 mar 2022 12:31:21
0

Algunas respuestas son bastante complejas, escribí esta solución que es bastante básica de entender (creo/espero):

$args = array( 'post_type' => 'Teammember','posts_per_page' =>  -1);
$loop = new WP_Query($args);
if ( $loop->have_posts() ) {
     while ( $loop->have_posts() ) {
         $loop->the_post();
         $id = get_the_id();
         $name = get_the_terms( get_the_ID(), 'teammember-category' );
         $sort[$id] = $name[0]->name;
    }
}
wp_reset_postdata();
asort($sort);
$result = array_keys($sort);

Ahora la variable $result contiene todos los IDs de los posts, ordenados ascendentemente por el nombre de la taxonomía personalizada. Precaución: si un post contiene múltiples categorías, se necesita una solución diferente.

Puedes usar los IDs en una función foreach, algo así:

foreach($result as $id){
$image = get_the_post_thumbnail($id);
...etc.
} 

o puedes hacer una segunda consulta como esta:

$loopnew = new WP_Query(array('post_type' => 'Teammember','post__in'=> $result));
if ( $loopnew->have_posts() ) {
     while ( $loopnew->have_posts() ) {
         $loopnew->the_post();
         ...etc.
     }
 }
15 feb 2023 19:45:56
0
-1

Es un poco molesto que WordPress no te permita hacer eso y te obligue a tener básicamente dos campos con la misma información..

PERO aquí comparto mi solución. La idea es pasar todos los términos de taxonomías seleccionados a la información meta del post.

(Ten cuidado, necesitarás ajustarlo si tu taxonomía permite múltiples valores)

//agrega este hook para guardar automáticamente los términos como metadatos del post cuando guardas un post
add_action('save_post', 'add_custom_taxonomies_as_post_meta', 10, 1);
function add_custom_taxonomies_as_post_meta($id)
{
  $current_post = get_post($id);
  $taxonomies  = get_object_taxonomies($current_post);
  foreach ($taxonomies as $tax) {
    $post_terms = get_the_terms($id, $tax);
    $term = $post_terms[0];
    add_post_meta($id, $tax,  $term->name, true);
  }
}

Después de colocar esto en tu functions.php puedes usar meta_key y orderby como siempre para ordenar tus posts así:

   'meta_key' => TU-TAXONOMIA,
    'orderby'    => array(
      'meta_value' => 'ASC'
    )

Espero que esto sea útil para alguien.

14 jul 2022 15:43:13