Usando wp_query, ¿es posible ordenar por taxonomía?

44

Mi pregunta es simple, estoy usando WP_Query para recuperar algunas publicaciones de tipo personalizado que se filtran por una taxonomía utilizando tax_query.

Ahora mi problema es que me gustaría ordenar la taxonomía, pero a partir de la documentación y la búsqueda en la web no puedo encontrar una solución.

El orden en WP_Query le permite ordenar por un grupo de campos, incluso campos de metadatos personalizados, pero no parece admitir taxonomía.

¿Algún puntero en la dirección correcta?

Gracias a todos.

    
pregunta yeope 08.04.2011 - 17:44

9 respuestas

13

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

Las taxonomías son formas de agrupar cosas. Entonces, el punto de tener una taxonomía en las publicaciones sería tener términos en esa taxonomía que se comparten entre las publicaciones. Si una taxonomía tuviera términos que solo se usaran en una publicación cada uno, entonces la taxonomía sería inútil. Y si los términos se compartieran como deberían ser, el ordenamiento por ellos no produciría nada particularmente útil.

Lo que deberías estar usando en tal situación es el post meta. Puedes ordenar por meta de publicación, y es único para cada publicación.

Editar: Dicho esto, puede hacer su pedido por taxonomía haciendo una consulta SQL personalizada usando un filtro, simplemente no puede hacerlo desde un WP_Query no modificado: enlace

Sin embargo, si tiene que recurrir a este tipo de cosas, entonces su estructura de diseño de datos es incorrecta en primer lugar. Los "términos" en la taxonomía no son "datos" reales. Los términos en sí no tienen un significado inherente, solo son etiquetas para la agrupación particular que están describiendo. Si los trata como datos significativos, tiene un defecto de diseño subyacente.

Las taxonomías agrupan cosas asignándoles términos. Esa agrupación es el punto central de las taxonomías, los términos son simplemente caras bonitas de la agrupación. Si tiene metadatos significativos para asignar a una publicación, entonces debería estar usando el meta de publicación. Y que puede ordenar, porque el meta meta usa claves y valores para almacenar información. Con una taxonomía, en realidad solo está almacenando claves, y sus valores son las publicaciones agrupadas por ese término.

Las cosas son más fáciles a largo plazo si utiliza el enfoque correcto para ello. Si bien no estoy diciendo que no puedas hacer algo extraño con la taxonomía, a la larga solo estás haciendo las cosas más difíciles para ti al usarlo de forma incorrecta.

    
respondido por el Otto 08.04.2011 - 18:20
36

La respuesta aceptada para esta pregunta es inaceptable. Es ilógico suponer que ordenar por impuestos "no tiene sentido". La respuesta que dio no tiene sentido.

Considera tener un tipo de entrada de menú. Entonces usted tiene un impuesto personalizado de "Categorías de Alimentos". El impuesto FoodCategories tiene los términos "Desayuno", "Almuerzo" y "Cena". Si envía una consulta utilizando el parámetro tax_query, ahora tiene un conjunto de resultados con todos los términos, sin embargo, están ordenados por fecha de publicación.

Para obtener el orden correcto de estos, en relación con sus términos, y luego mostrarlos en la parte delantera de manera apropiada al separar las publicaciones en sus diversas categorías, debe recorrer el conjunto de resultados y luego consultar a cada individuo. publicar dentro del conjunto de resultados para encontrar sus términos y comparar con el término actual, filtrar en una matriz y continuar a lo largo. Luego tienes que volver a recorrer la nueva matriz para mostrar. Esto no es productivo.

Sería bueno si WP tuviera una opción "byby_index.in" en lugar de "post__in", pero dado que no es así, también tiene que hacer el proceso ridículo anterior; personalice la consulta por sí mismo mediante el filtro 'posts_ordenada' y el filtro 'posts_join' para ajustar el método order by y agregar el término al conjunto de resultados, respectivamente; o tiene que hacer una nueva consulta para cada término que está filtrando dentro de las secciones html relativas a esos términos.

Lo más eficiente sería cambiar la cadena de consulta por medio de filtros. Lo más fácil sería hacer tres consultas separadas. La API de WP debe estar manejando los pedidos por impuestos o cualquier parámetro de consulta restrictivo. Si está restringiendo una consulta en función de ciertas condiciones, existe una alta probabilidad de que muchas tengan que realizar el pedido según esas mismas condiciones.

    
respondido por el Aryan Duntley 28.07.2014 - 13:36
13

Sí, pero está bastante involucrado ...

Agrega a functions.php en 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 frankensteined de algunas cosas encontradas y algunas cosas que hice yo mismo. Explicar es bastante difícil, pero la conclusión es que con esta ejecución, puedes poner? Orderby = (var. De consulta de taxonomía) y amp; order = ASC (o DESC) y ¡se irá!

    
respondido por el Drew Gourley 08.04.2011 - 18:36
8

Llego tarde al juego aquí, pero hay una forma más simple de hacer WordPressy para hacer esto.

Cree su consulta de impuestos como de costumbre.

$tax_query = array();
$tax_query['relation']="OR";
$tax_query[] = array(
    'taxonomy' => 'product_cat',
    'field'    => 'slug',
    'terms'    => $cat_terms,
);
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

Configure sus argumentos para query_posts o WP_Query

$args = array(
    'post_type'=>'post',
    'posts_per_page'=>12,
    'paged'=>$paged,
    'tax_query' => $tax_query,
);

Antes de realizar su consulta query_posts / WP_Query, enganche en el filtro orderby y anúlelo

add_filter('posts_orderby', 'edit_posts_orderby');
function edit_posts_orderby($orderby_statement) {
    $orderby_statement = " term_taxonomy_id ASC ";
    return $orderby_statement;
}
query_posts($args);
remove_filter('posts_orderby', 'edit_posts_orderby');

no olvides eliminar el filtro después ...

esto funciona b / c. tax_query crea las uniones, etc. para usted, solo necesita ordenar por uno de los campos de la unión.

    
respondido por el Francis Yaconiello 31.10.2014 - 14:48
2

Bueno, me gustaría exponer mi experiencia en la clasificación de tipos de publicaciones personalizadas por categoría / taxonomía.

LA WEB

  1. Un sitio web de agencia de viajes que se ejecuta en WordPress
  2. El contenido principal en el tipo de publicación personalizada se llama ‘ruta’
  3. Taxonomía con esta estructura Tipo de viaje > continente > país

EL CASO

En las páginas de la lista de categorías de archivos, el cliente quería que las publicaciones se ordenaran por

  1. El continente, ordenado por número de rutas en cada una.
  2. El país, ordenado alfabéticamente.

LOS PASOS

Primero , detecto la solicitud de la consulta de la página de archivo no modificada 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

En segundo lugar , edité el código sql en Sequel Pro contra la base de datos para satisfacer mis necesidades. Salgo con esto (sí, probablemente pueda mejorarse: mi conocimiento sobre MySQL no es excepcional):

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  

En tercer lugar , 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 gancho pre_get_post de acuerdo con 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

    
respondido por el Xavier Caliz 04.01.2015 - 16:09
2

Tuve un problema muy similar con el que traté: quiero pedir un archivo de tipo post personalizado (artículos de revistas) por una taxonomía (temas) personalizados. Nunca hago consultas de SQL directas en mi sitio, y generalmente, si usted es como estas otras respuestas, necesita reconsiderar su enfoque.

PROBLEMAS:

1) Wordpress no le permite ordenar taxonomías de ninguna manera inteligente.

2) Wordpress simplemente no permite que orderby use taxonomías en el post-tipo WP_Query (como lo explica Otto).

SOLUCIONES:

1) La clasificación de las taxonomías se realiza mejor mediante la Complemento de Taxonomía Orden NE en este momento. Te permite ordenar la taxonomía a través de WYSIWYG en wp-admin , que no es como lo haría pero no he encontrado nada mejor.

Cuando configures el complemento, obtendrás algo similar a lo que he hecho aquí. Tome nota de la opción Auto-sort Queries of this Taxonomy - establezca esto en Custom Order as Defined Above ; esto te da el pedido que necesitas. Captura de pantalla:

2)Conunataxonomíaordenadaensulugar,ahorapuedecrearunaseriedellamadasWP_Queryqueseejecutanatravésdecadatérmino,creandoefectivamenteunarchivoordenadoporlataxonomía.Useget_terms()paracrearunamatrizdetodoslostérminosdeimpuestos,luegoejecuteunforeachsobrecadatérmino.EstocreaunWP_Queryparacadaelementodetérminoquedevolverátodaslaspublicacionesparauntérminodeterminado,creandoefectivamenteunarchivoordenadoportérminodetaxonomía.Códigoparaqueestosuceda:

//Getyourtermsandputthemintoanarray$issue_terms=get_terms(['taxonomy'=>'issues','hide_empty'=>false,]);//Runforeachovereachtermtosetupqueryanddisplayforpostsforeach($issue_termsas$issue_term){$the_query=newWP_Query(array('post_type'=>'post','tax_query'=>array(array('taxonomy'=>'issues','field'=>'slug','terms'=>array($issue_term->slug),'operator'=>'IN'))));//Runloopovereachquerywhile($the_query->have_posts()):$the_query->the_post();//YOURTEMPLATEOUTPUTFOREACHPOSTendwhile;}

Lecturarelacionadaenestesitio: Mostrar todas las publicaciones en un tipo de mensaje personalizado, agrupado por una taxonomía personalizada

    
respondido por el staypuftman 10.04.2017 - 16:45
1

Aquí está la solución que he usado para este problema en particular. Esta solución es para casos extremos en los que no es posible utilizar un filtro pre_get_posts y existe una paginación en la consulta (es decir, 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})"; // Add further specific ordering here

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

Lo he usado para crear un menú de navegación ordenado por taxonomía, término y número de publicaciones por término.

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

    
respondido por el CodeShaman 24.03.2017 - 17:48
1

No estoy seguro de por qué todas las soluciones aquí están exagerando. OK, hace media década, pero actualmente estoy ejecutando el siguiente código y funciona:

   <?php // Default
    $wheels_args = array(
        'post_type' => 'wheels',
        'posts_per_page' => '96',
        'orderby' => 'taxonomy, name', // Just enter 2 parameters here, seprated by comma
        'order'=>'ASC'
    );
    $loop = new WP_Query($wheels_args);
    ?>

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

    
respondido por el user3135691 06.07.2017 - 14:26
0

Es como una consulta antes de la consulta, pero no nos molestará si no estamos consultando demasiadas publicaciones ... La idea es modificar la consulta principal para que ni siquiera tengamos que 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() ) { // 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' );
    
respondido por el Marcelo Viana 22.04.2017 - 08:38

Lea otras preguntas en las etiquetas