Esegui una query per ordinare prima un elenco per meta chiave (se esiste) e mostrare i post rimanenti senza meta chiave ordinati per titolo


22

Sto lavorando a un modello di pagina dei termini di tassonomia personalizzata in cui vogliamo che gli articoli collegati al termine siano ordinati in base a una data di pubblicazione (campo data personalizzato) e se ci sono più elementi nello stesso giorno (formattati come AAAA-MM- DD) per ordinare quelli per titolo e infine ordinare per titolo se il campo personalizzato non è stato compilato (elementi precedenti).

Quindi, l'ho provato in centinaia di modi diversi con un WP_query e restituisce la maggior parte dei risultati come li desidero, ma in questo caso restituisce solo gli elementi che hanno la meta_key di publishing_date. Tutti gli altri elementi vengono ignorati e non visualizzati. Ho provato una meta_query usando una relazione di "o" e ho confrontato la pubblicazione_data come EXISTS e NOT EXISTS, ma ciò ha restituito 0 risultati per me.

Inoltre, il sito è ancora in esecuzione 3.5.2 e non vogliono aggiornarlo.

Ecco la mia query più recente che mi ottiene i post con il campo personalizzato publishing_date visualizzato nell'ordine corretto:

$term = get_queried_object(); // find the term of the taxonomy page we are on
$wp_query = new WP_Query( array(
'post_type' => 'resource',
'tax_query' => array(
    array(
        'taxonomy' => 'resource_types',
        'field' => 'slug',
        'terms' => $term->name,
    )), 

'meta_key' => 'publication_date',
'orderby' => 'meta_value_num',
'order' => 'DESC',
'paged' => $paged,
'posts_per_page' => '10',
));

Ho anche provato a utilizzare wpdb ed eseguire una query SQL, ma non sono sicuro di come realizzare ciò che voglio. Se qualcuno mi potesse aiutare sarebbe fantastico!

Grazie in anticipo.


Sorpreso l'approccio meta_query non ha funzionato, ma di nuovo non è possibile ordinare il valore meta con una meta_query senza aver impostato la meta_key.
sanchothefat,

Penso che sia questo il problema. Finalmente ho ottenuto una meta query funzionante: 'meta_query' => array( 'relation' => 'OR', array( //check to see if date has been filled out 'key' => 'publication_date', 'compare' => '!=', 'value' => date('Y-m-d'), ), array( //if no date has been added show these posts too 'key' => 'publication_date', 'value' => date('Y-m-d'), 'compare' => 'NOT EXISTS' ) ),ma l'ordinamento non funziona: \
CSSgirl il

sì, l'ordinamento si basa purtroppo sul fatto che meta_key sia impostato al di fuori di tax_query. La mia risposta qui sotto potrebbe essere di aiuto.
sanchothefat,

Risposte:


19

Grazie a tutti per il vostro aiuto!

Alla fine la query qui sotto mi ha dato i risultati che desideravo - che era quello di mostrare e ordinare i messaggi in base a un campo personalizzato di "publishing_date" per primo - l'ordinamento per data e se ce ne fossero multipli della stessa data (diciamo, 4 contrassegnati Giugno 2013), ordinerebbe quelli per titolo. Quindi, dopo che scorre tutti i post in cui è stata inserita la Data di pubblicazione, scorrerà nuovamente i post rimanenti, in ordine alfabetico per titolo.

Questo mi fa ottenere i risultati impostati nella stessa query e mantiene la mia impaginazione:

$term = get_queried_object();
the_post();
$wp_query = new WP_Query( array(
'post_type' => 'resource',
    'tax_query' => array(
        array(
            'taxonomy' => 'resource_types',
            'field' => 'slug',
            'terms' => $term->name,
        )),
 'meta_query' => array(
       'relation' => 'OR',
        array( //check to see if date has been filled out
                'key' => 'publication_date',
                'compare' => '=',
                'value' => date('Y-m-d')
            ),
          array( //if no date has been added show these posts too
                'key' => 'publication_date',
                'value' => date('Y-m-d'),
                'compare' => 'NOT EXISTS'
            )
        ),
'meta_key' => 'publication_date',
'orderby' => 'meta_value title',
'order' => 'ASC',
'paged' => $paged,
'posts_per_page' => '10',
));

1
Bello. Non avrei mai pensato di farne due meta_querysulla stessa chiave!
GhostToast,

5
Per me (usando WordPress 4.1.1), se lo imposto meta_keyautomaticamente non lo include nemmeno con NOT EXISTS. Spero davvero di fare qualcosa di sbagliato.
Ryan Taylor,

1
@RyanTaylor stesso qui - meta_key non deve essere impostato nella query perché funzioni, ma sembra ordinarsi correttamente in base al valore meta anche quando la meta chiave non è impostata.
jammypeach,

2
Come sopra i commenti, per WP 4.1+ rimuovi o commenta 'meta_key' => 'publication_date',.
MikeiLL,

7

Pochi anni dopo, il codice pubblicato da CSSGirl non funzionava per me perché c'erano alcuni post che non avevano la meta-chiave o la meta-chiave era vuota, quindi questo è quello che dovevo fare per avere tutti i messaggi ordinati per data e mostra prima quelli con un valore di meta chiave:

$args          = array(
'post_type'   => $type,
'post_status' => 'publish',
'nopaging'    => TRUE,
'meta_query'  => array(
    'relation' => 'OR',
    array(
        'key'     => $meta_key,
        'compare' => 'NOT EXISTS',
    ),
    array(
        'relation' => 'OR',
        array(
            'key'   => $meta_key,
            'value' => 'on',
        ),
        array(
            'key'     => $meta_key,
            'value'   => 'on',
            'compare' => '!=',
        ),
    ),
),
'orderby'     => array( 'meta_value' => 'DESC', 'date' => 'DESC' ),
);

1

Penso che dovresti fare 2 loop separati. Puoi catturare tutti i post trovati nel primo loop ed escluderli dal loop secondario abbastanza facilmente:

$found_posts = array();
while($loop->have_posts()): $loop->the_post();
    // loop stuff
    $found_posts[] = get_the_id();
endwhile;

wp_reset_query();

$args = array(
    // other args
    'post__not_in' => $found_posts,
);

Quindi esegui il tuo secondo ciclo.


Provando questo ora, grazie. Ti farà sapere se funziona!
CSSgirl,

1
questo ha funzionato - ma ha rotto l'impaginazione - hai idea di come farlo funzionare? Ecco come appare ora:echo paginate_links( array( 'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ), 'format' => '?page=%#%', 'current' => max( 1, get_query_var('paged') ), 'total' => $publication_query->max_num_pages, 'prev_text' => __('Previous |'), 'next_text' => __('| Next'), ) );
CSSgirl,

Hmm. Non che io possa pensare.
GhostToast,

1

C'è qualche motivo per cui non è possibile imporre la meta chiave pubblicazioni_date per ogni post solo con un valore vuoto?

Quindi nella tua save_postazione aggiungerai / aggiornerai la meta-chiave se il $_POSTvalore è vuoto o meno.

Dovresti eseguire uno script di aggiornamento per scorrere i tuoi post precedenti e aggiungere la chiave con un valore vuoto, ad esempio:

add_action( 'admin_init', 'update_old_posts' );
function update_old_posts() {
    if ( ! isset( $_GET[ 'update_old_posts' ] ) )
         return;

    foreach( get_posts() as $post ) {
        if ( false === get_post_meta( $post->ID, 'publication_date', true ) ) {
             update_post_meta( $post->ID, 'publication_date', '' );
             echo "Updated {$post->post_title} <br />";
        }
    }

    die;
}

Eseguilo navigando su http://example.com/wp-admin/?update_old_posts

Quindi puoi utilizzare la stessa query che hai. Potresti voler aggiungere un filtro aggiuntivo per consentirti di ordinare in base a colonne diverse in direzioni diverse, sarebbe logico per me ordinare per data in ordine decrescente e titolo in ordine crescente.

add_filter( 'posts_orderby', 'multicolumn_orderby', 10, 2 );
function multicolumn_orderby( $orderby, $query ) {
    global $wpdb;

    // check it's the right query
    if ( $query->get( 'meta_key' ) == 'publication_date' ) {
         $orderby = "$wpdb->postmeta.meta_value+0 DESC, $wpdb->posts.post_title ASC";
    }

    return $orderby;
}

Hmm, non ci ho pensato. Lo proverò e vedrò come va, grazie!
CSSgirl,

0

Ho creato una clausola where personalizzata. L'ho provato usando $wp_query->requestprima del mio ciclo principale, non conosco davvero bene SQL, ma questo sembra far funzionare le cose.

add_action('pre_get_posts', 'add_trending_sort', 11, 1);
function add_trending_sort($query){
  if(!$query->is_main_query())
    return;

  //Overwrite query arguments
  $query->set('meta_query', array(
    array(
      'key' => 'TRENDING',
      //'value' => 'asdfasdf',//may need a value for older versions of WordPress
      'compare' => 'NOT EXISTS',
    )
  ));
  $query->set('orderby', 'meta_value_num date');
  $query->set('order', 'DESC');
}

add_filter('posts_where', 'add_trending_where');
function add_trending_where($where = ''){
  global $wpdb, $wp_query;
  if(!$wp_query->is_main_query())//Not sure if this really works.  Should be OK
    return $where;

  $where .= " OR ( $wpdb->postmeta.meta_key = 'TRENDING' )";

  // Don't run this twice
  remove_filter('posts_where', 'add_trending_where');

  return $where;
}

In alternativa, è possibile impostare compareper 'EXISTS'e cambiare la linea in add_trending_where a $where .= " OR ($wpdb->postmeta.post_id IS NULL)";. Quindi dovresti cambiare il valore della chiave in un solo posto. Ancora una volta, $wp_query->requestfai eco e gioca se vuoi capirlo meglio o modificarlo.

EDIT: ho appena notato che non funziona se meta_keyimpostato sulla query. Puoi usare $query->set('meta_key', NULL);se devi.

EDIT 2: Ho ottenuto questo lavoro con il metodo sopra. Per qualche motivo non è stato all'inizio (forse è stato impostato meta_key ... Non lo so).

add_action('pre_get_posts', 'add_trending_sort', 11, 1);
function add_trending_sort($query){
  // Bail if not the main "hidden" query, as opposed to a 'new WP_Query()' call
  if(!$query->is_main_query())
    return;

  // Set meta_query to get shares for orderby, and also get non-shared content.
  $query->set('meta_query', array(
    'relation' => 'OR',
    array(
      'key' => 'TRENDING',
      'compare' => 'NOT EXISTS',
    ),
    array(
      'key' => 'TRENDING',
      'compare' => 'EXISTS',
    )
  ));
  //$query->set('meta_key', NULL);
  $query->set('orderby', array('meta_value_num' => 'DESC', 'date' => 'DESC'));
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.