Ordinare post per tassonomia e valore meta in WordPress
È 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',
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.
