it-swarm.com.de

Bestellung über optionalen Metaschlüssel?

Ich erstelle die Sortierfunktion für einen benutzerdefinierten Beitragstyp und habe einen benutzerdefinierten Metawert für "Empfohlene" Beiträge. Dieser Wert wird festgelegt, wenn Sie das Kontrollkästchen aktivieren, andernfalls wird er nicht festgelegt.

Wenn Sie den Standard-orderby=meta_value mit meta_key=featured verwenden, werden auf dem Bildschirm nur Posts mit dem Metaschlüssel angezeigt. Wenn nicht, erscheinen sie nicht einmal.

Ich möchte es so, wenn es nicht gesetzt ist, erscheinen sie, aber sie erscheinen zuletzt. Ich gehe davon aus, dass ich stattdessen meta_query verwenden muss, aber ich konnte das auch nicht zum Laufen bringen.

Wie erlaube ich leere, falsche oder nicht vorhandene Metaschlüssel in den WP_Query-Argumenten?

Mein Code ist unten. Hiermit werden die Spalten im Dashboard sortiert, sodass die standardmäßigen WP Abfrageargs geändert werden.

function featured_sortable_order( $vars ) {
  if ( isset($vars['orderby']) && $vars['orderby'] == 'featured' ) {

    $vars = array_merge( $vars, array(
      'meta_key' => 'featured',
      'orderby' => 'meta_value',
      'order'     => isset($vars['order']) ? $vars['order'] : 'asc',
    ) );

  }
  return $vars;
}
add_filter( 'request', 'featured_sortable_order' );
6
Radley Sustaire

Nach der Erstveröffentlichung vollständig bearbeitet

Das Problem ist, dass WordPress zum Bestellen eines Meta-Werts 'meta_key' in der Abfrage auf etwas setzen muss. Aber wenn Sie 'meta_key' auf etwas setzen, wird WordPress so etwas hinzufügen

AND ( wp_postmeta.meta_key = 'the_meta_key' )

zu WHERE SQL-Klausel; und so ähnlich

INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )

zu join Klauseln. Deshalb gibt query nur die Posts zurück, die diese Meta-Abfrage enthalten.

Wenn Sie erst einmal am Backend gearbeitet haben und get_post_meta( $postid, 'featured', true) aufgerufen haben, damit in jedem Beitrag die Spalte angezeigt wird, ist dies dank des WordPress-Caches beim Abrufen der Metafunktion kein großes Leistungsproblem.

Die Idee ist also, alle Beiträge zu erhalten (ohne Filter für Metaschlüssel hinzuzufügen), dann Beiträge mit 'posts_results' zu filtern und Beiträge zu bestellen, die den 'vorgestellten' Metaschlüssel betrachten.

Ich werde den Filter entfernen, sobald ich ihn benutzt habe.

add_filter( 'posts_results', 'order_by_featured', PHP_INT_MAX, 2 );

function order_by_featured ( $posts, $query ) {
  // run only on admin, on main query and only if 'orderby' is featured
  if ( is_admin() && $query->is_main_query() && $query->get('orderby') === 'featured' ) {
    // run once
    remove_filter( current_filter(), __FUNCTION__, PHP_INT_MAX, 2 );
    $nonfeatured = array();
    $featured = array();
    foreach ( $posts as $post ) {
      if ( get_post_meta( $post->ID, 'featured', TRUE ) ) {
        $featured[] = $post;
      } else {
        $nonfeatured[] = $post;
      }
    }
    $order = strtoupper( $query->get('order') ) === 'ASC' ? 'DESC' : 'ASC';
    // if order is ASC put featured at top, otherwise put featured at bottm
    $posts = ( $order === 'ASC' )
      ? array_merge( $nonfeatured, $featured )
      : array_merge( $featured, $nonfeatured );
  }
  return $posts;
}

Außerdem füge ich einen Filter für 'pre_get_post' hinzu, um 'ASC' als Standardreihenfolge zu verwenden, wenn in der Abfrage keine Reihenfolge festgelegt ist:

add_action( 'pre_get_posts', function( $query ) {
  // if no order is set set order to ASC
  if (
    is_admin() && $query->is_main_query()
    && $query->get('orderby') === 'featured' 
    && $query->get('order') === ''
  ) {
    $query->set( 'order', 'ASC' );
  }
});
6
gmazzap