Fragen Sie nach, ob eine Liste zuerst nach Metaschlüssel sortiert werden soll (sofern vorhanden), und zeigen Sie die verbleibenden Beiträge ohne Metaschlüssel nach Titel sortiert an

22

Ich arbeite an einer benutzerdefinierten Taxonomiebegriffseitenvorlage, in der die mit dem Begriff verknüpften Elemente nach Veröffentlichungsdatum sortiert werden sollen (benutzerdefiniertes Datumsfeld) - und wenn mehrere Elemente am selben Tag vorhanden sind (Formatierung wie JJJJ-MM). DD), um diese nach Titel und schließlich nach Titel zu sortieren, wenn das benutzerdefinierte Feld nicht ausgefüllt wurde (ältere Elemente).

Also habe ich es auf hundert verschiedene Arten mit einer WP_query versucht und es gibt die meisten Ergebnisse so zurück, wie ich sie haben möchte - aber in diesem Fall gibt es nur die Elemente zurück, die den meta_key von publication_date haben. Alle anderen Elemente werden ignoriert und nicht angezeigt. Ich habe eine meta_query mit der Beziehung "oder" ausprobiert und das publication_date als EXISTS und NOT EXISTS verglichen, aber das ergab 0 Ergebnisse für mich.

Außerdem wird auf der Site noch 3.5.2 ausgeführt, und sie möchten kein Upgrade durchführen.

Hier ist meine letzte Abfrage, mit der ich die Posts erhalte, bei denen das benutzerdefinierte Feld publication_date in der richtigen Reihenfolge angezeigt wird:

$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',
));

Ich habe auch versucht, wpdb zu verwenden und eine SQL-Abfrage auszuführen, bin mir aber nicht sicher, wie ich das erreichen soll. Wenn mir jemand helfen könnte, wäre das großartig!

Danke im Voraus.

CSSgirl
quelle
Überrascht hat der meta_query-Ansatz nicht funktioniert, aber andererseits können Sie mit einer meta_query nicht nach Meta-Wert bestellen, ohne den meta_key gesetzt zu haben.
Ranchothefat
Ich denke, das ist das Problem, das ich habe. Ich habe endlich eine Meta-Abfrage erhalten: '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' ) ),aber die Bestellung funktioniert nicht: \
CSSgirl
Ja, die Bestellung hängt leider davon ab, dass meta_key außerhalb der tax_query gesetzt ist. Meine Antwort unten könnte jedoch helfen.
sanchothefat

Antworten:

19

Vielen Dank für Ihre Hilfe!

Am Ende brachte mir die folgende Abfrage die gewünschten Ergebnisse - die Beiträge sollten zuerst in einem benutzerdefinierten Feld von "publication_date" angezeigt und sortiert werden - sortiert nach dem Datum und wenn mehrere vom selben Datum vorhanden waren (z. B. 4 markiert) Juni 2013), würde es diese nach Titel sortieren. Nachdem alle Posts mit ausgefülltem Veröffentlichungsdatum durchlaufen wurden, werden die verbleibenden Posts in alphabetischer Reihenfolge nach Titel durchlaufen.

Dadurch erhalte ich die in derselben Abfrage festgelegten Ergebnisse und behalte meine Paginierung bei:

$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',
));
CSSgirl
quelle
1
Nett. Ich hätte nie gedacht, zwei meta_queryauf dem gleichen Schlüssel laufen zu lassen!
GhostToast
5
Für mich (mit WordPress 4.1.1), wenn ich meta_keyes automatisch einstelle, wird es nicht einmal mit einbezogen NOT EXISTS. Ich hoffe wirklich, dass ich etwas falsch mache.
Ryan Taylor
1
@RyanTaylor dasselbe hier - meta_key muss nicht in der Abfrage gesetzt sein, damit dies funktioniert, aber es scheint nach Meta-Wert korrekt zu ordnen, auch wenn der Meta-Schlüssel nicht gesetzt ist.
Jamypeach
2
Wie oben beschrieben, entfernen oder kommentieren Sie WP 4.1+ aus 'meta_key' => 'publication_date',.
MikeiLL
7

Einige Jahre später funktionierte der von CSSGirl gepostete Code nicht für mich, da es einige Posts gab, bei denen der Metaschlüssel nicht vorhanden war oder der Metaschlüssel leer war. Deshalb musste ich dies tun, um alle Posts nach Datum zu ordnen und zeigen Sie zuerst diejenigen mit einer Metaschlüsselwertanzeige an:

$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' ),
);
Ciprian Tepes
quelle
1

Ich denke, Sie müssten 2 separate Loops machen. Sie können alle in der ersten Schleife gefundenen Beiträge erfassen und sie einfach genug aus der sekundären Schleife ausschließen:

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

Führen Sie dann Ihre zweite Schleife aus.

GhostToast
quelle
Ich versuche es jetzt, danke. Werden Sie wissen lassen, ob es funktioniert!
CSSgirl
1
das hat funktioniert - aber es hat die Paginierung gebrochen - irgendeine Idee, wie man das zum Laufen bringt? So sieht es jetzt aus: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. Nicht, dass ich mir vorstellen könnte.
GhostToast
1

Gibt es einen Grund, warum Sie den Metaschlüssel publication_date nicht für jeden Beitrag nur mit einem leeren Wert erzwingen können?

In Ihrer save_postAktion würden Sie also den Metaschlüssel hinzufügen / aktualisieren, unabhängig davon, ob der $_POSTWert leer ist oder nicht.

Sie müssten ein Update-Skript ausführen, um Ihre älteren Beiträge zu durchlaufen und den Schlüssel mit einem leeren Wert hinzuzufügen. Beispiel:

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

Führen Sie es aus, indem Sie zu http://example.com/wp-admin/?update_old_posts navigieren

Dann können Sie die gleiche Abfrage verwenden, die Sie haben. Wenn Sie einen zusätzlichen Filter hinzufügen möchten, damit Sie nach verschiedenen Spalten in verschiedene Richtungen sortieren können, ist es für mich sinnvoll, nach Datum in absteigender Reihenfolge und nach Titel in aufsteigender Reihenfolge zu sortieren.

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;
}
sanchothefat
quelle
Hmm, daran habe ich nicht gedacht. Ich werde es versuchen und sehen, wie es geht, danke!
CSSgirl
0

Ich habe eine benutzerdefinierte where-Klausel erstellt. Ich habe es mit $wp_query->requestdirekt vor meiner Hauptschleife getestet , ich kenne SQL nicht so gut, aber das schien die Dinge zum Laufen zu bringen.

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

Alternativ könnten Sie setzen compareauf 'EXISTS'und die Linie in add_trending_where ändern $where .= " OR ($wpdb->postmeta.post_id IS NULL)";. Dann müssten Sie nur den Wert des Schlüssels an einer Stelle ändern. Nochmals, hören Sie zu $wp_query->requestund spielen Sie herum, wenn Sie dies besser verstehen oder optimieren möchten.

BEARBEITEN: Mir ist gerade aufgefallen, dass dies nicht funktioniert, wenn meta_keyin der Abfrage festgelegt ist. Sie könnten verwenden, $query->set('meta_key', NULL);wenn Sie müssen.

EDIT 2: Ich habe dies mit der obigen Methode funktioniert. Aus irgendeinem Grund war es zuerst nicht (vielleicht wurde meta_key gesetzt ... ich weiß es nicht).

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'));
}
Ryan Taylor
quelle