Ordinare post per tassonomia e valore meta in WordPress

7 mar 2014, 17:50:18
Visualizzazioni: 13.6K
Voti: 3

È possibile ordinare i post per Meta Value.

È possibile ordinare i post per più valori.

E grazie al codice seguente è possibile ordinare per tassonomia.

Ma come posso modificare il codice qui sotto per ordinare per tassonomia E meta_value?

Aggiunto a functions.php

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

Aggiunto a index.php

<?php $args = array(
'post_type' => 'custom_post_type',
'posts_per_page' => -1,
'meta_key' => '_EventStartDate',
'orderby' => 'taxonomy_cat',
'order' => asc
);
$the_query = new WP_Query( $args );

if ( $the_query->have_posts() ) : while ( $the_query->have_posts() ) : $the_query-    >the_post(); ?>

etc. etc.

Modificare questo non funziona

'orderby' => 'taxonomy_cat meta_value',
0
Tutte le risposte alla domanda 1
0

Nel tuo codice c'è

if ( isset( $wp_query->query['orderby'] ) && $taxonomy == $wp_query->query['orderby'] 

che fa sì che il tuo codice non funzioni con più campi di ordinamento, perché se imposti

'orderby' => 'taxonomy_cat meta_value'

allora $taxonomy == $wp_query->query['orderby'] non sarà mai vero.

Inoltre, ho notato che ciclare attraverso tutte le tassonomie solo per trovare quella da ordinare è poco performante e non molto affidabile.

Quindi ho modificato leggermente il tuo codice: quando vuoi ordinare per una tassonomia, il tuo argomento dovrebbe essere qualcosa come:

'orderby' => 'taxonomy.taxonomy_cat'

grazie al prefisso 'taxonomy.' è facile riconoscere la tassonomia e non c'è bisogno di ciclare attraverso tutte le tassonomie.

Inoltre, WordPress permette di passare solo un argomento come 'order', quindi quando passi più argomenti 'orderby', il risultato potrebbe non essere quello atteso.

Quindi ho modificato il tuo codice per accettare un argomento aggiuntivo: 'ordertax'. Ovviamente è opzionale, quindi se non lo passi, verrà usato l'argomento 'order'. Viene anche ignorato se 'orderby' non contiene alcun argomento di tassonomia. Se usi più argomenti 'orderby' senza passare 'ordertax', tutti gli argomenti verranno ordinati in base all'argomento 'order' (o il default 'DESC'), quindi usando

'orderby' => 'taxonomy.taxonomy_cat meta_value',
'order' => 'ASC'

significa "ORDERBY taxonomy_cat ASC, meta_value ASC", mentre usando

'orderby' => 'taxonomy.taxonomy_cat meta_value',
'ordertax' => 'DESC'
'order' => 'ASC'

significa "ORDERBY taxonomy_cat DESC, meta_value ASC".

Ecco ora il codice:

function orderby_tax_clauses( $clauses, $wp_query ) {
  $orderby_arg = $wp_query->get('orderby');
  if ( ! empty( $orderby_arg ) && substr_count( $orderby_arg, 'taxonomy.' ) ) {
    global $wpdb;
    $bytax = "GROUP_CONCAT({$wpdb->terms}.name ORDER BY name ASC)";
    $array = explode( ' ', $orderby_arg ); 
    if ( ! isset( $array[1] ) ) {
      $array = array( $bytax, "{$wpdb->posts}.post_date" );
      $taxonomy = str_replace( 'taxonomy.', '', $orderby_arg );
    } else {
      foreach ( $array as $i => $t ) {
        if ( substr_count( $t, 'taxonomy.' ) )  {
          $taxonomy = str_replace( 'taxonomy.', '', $t );
          $array[$i] = $bytax;
        } elseif ( $t === 'meta_value' || $t === 'meta_value_num' ) {
          $cast = ( $t === 'meta_value_num' ) ? 'SIGNED' : 'CHAR';
          $array[$i] = "CAST( {$wpdb->postmeta}.meta_value AS {$cast} )";
        } else {
          $array[$i] = "{$wpdb->posts}.{$t}";
        }
      }
    }
    $order = strtoupper( $wp_query->get('order') ) === 'ASC' ? ' ASC' : ' DESC';
    $ot = strtoupper( $wp_query->get('ordertax') );
    $ordertax = $ot === 'DESC' || $ot === 'ASC' ? " $ot" : " $order";
    $clauses['orderby'] = implode(', ',
      array_map( function($a) use ( $ordertax, $order ) {
        return ( strpos($a, 'GROUP_CONCAT') === 0 ) ? $a . $ordertax : $a . $order;
      }, $array )
    );
    $clauses['join'] .= " LEFT OUTER JOIN {$wpdb->term_relationships} ";
    $clauses['join'] .= "ON {$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id";
    $clauses['join'] .= " LEFT OUTER JOIN {$wpdb->term_taxonomy} ";
    $clauses['join'] .= "USING (term_taxonomy_id)";
    $clauses['join'] .= " LEFT OUTER JOIN {$wpdb->terms} USING (term_id)";
    $clauses['groupby'] = "object_id";
    $clauses['where'] .= " AND (taxonomy = '{$taxonomy}' OR taxonomy IS NULL)";
  }
  return $clauses;
}

Usalo così:

$args = array(
  'post_type'      => 'custom_post_type',
  'posts_per_page' => -1,
  'meta_key'       => '_EventStartDate',
  'orderby'        => 'taxonomy.taxonomy_cat meta_value',
  'ordertax'       => 'ASC',
  'order'          => 'DESC'
);

add_filter( 'posts_clauses', 'orderby_tax_clauses', 10, 2 );
$the_query = new WP_Query( $args );
remove_filter( 'posts_clauses', 'orderby_tax_clauses', 10, 2 );

Nota che usare il mio codice (proprio come il tuo) con una WP_Query che contiene una query di tassonomia potrebbe causare problemi... per questo motivo è importante rimuovere il filtro dopo averlo usato.

7 mar 2014 23:51:32