Nach Metawert sortieren, aber Beiträge einschließen, die keinen haben


37

Ich habe die integrierte WP-Suche mithilfe des pre_get_postsFilters geändert, sodass der Benutzer die Beiträge (einschließlich einer Reihe benutzerdefinierter Beitragstypen) nach verschiedenen Feldern sortieren kann.

Das Problem, das ich habe, ist, dass wenn ich WP anweise, nach einem Meta-Wert zu sortieren, alle Posts ausgeschlossen werden, für die dieser Meta-Wert nicht festgelegt ist. Dies führt dazu, dass sich die Anzahl der Ergebnisse ändert, wenn Sie die Sortierung von "Preis" auf "Datum" ändern, da für "Beiträge" nicht "Preis" festgelegt ist, sondern "Artikel".

Dies ist nicht das, was ich will, also würde ich gerne wissen, ob es eine Möglichkeit gibt, ALLE Posts einzuschließen - auch diejenigen, denen der Meta-Wert fehlt, nach dem ich sortiere - und denjenigen ohne den letzten Wert zu setzen.

Ich weiß, wie man nach mehr als einem Feld sortiert, aber das hilft nicht.

Vielen Dank

Scheint, ich bin nicht der einzige mit dieser Frage: Wie kann ich Posts mit und ohne bestimmten meta_key in args for wp_query aufnehmen? aber da gibt es keine lösung.

Aktualisieren

Ich habe die Antwort ausprobiert, bin mir aber nicht sicher, ob ich sie richtig verstanden habe:

<?php
function my_stuff ($qry) {
    $qry->set('meta_query', array(array(
        'key' => 'item_price', 
        'value' => '', 
        'compare' => 'NOT EXISTS'
    )));

    $qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
    $qry->set('order', 'ASC DESC');
    $qry->set('meta_key', 'item_price');
}

Der Meta-Wert ist eine Zahl (er wird verwendet, um einen Preis zu speichern, wie der Name vermuten lässt.)

Update 2

Ich habe die Bestellung auskommentiert und alles, was ich jetzt habe, ist Folgendes:

<?php
$qry->set('meta_query', array(array(
    'key' => 'item_price', 
    'value' => '', 
    'compare' => 'NOT EXISTS'
)));

Mit diesem Code scheint die Abfrage alle Posts zurückzugeben, bei denen der item_priceSchlüssel fehlt, und keinen der Posts, bei denen er vorhanden ist. IE das Problem ist jetzt umgekehrt.

Wenn ich auch den Bestellcode hinzufüge, erhalte ich 0 Ergebnisse.

Edit: ... drei Jahre später ... : PI hatte dieses Problem erneut. Ich habe alle Antworten ausprobiert und keine funktioniert. Ich bin mir nicht sicher, warum manche Leute glauben, dass sie funktionieren, aber sie arbeiten zumindest nicht für mich.

Die Lösung, die ich gefunden habe, ist die Verwendung des save_postFilters - stellen Sie sicher, dass alle Beiträge das benutzerdefinierte Feld haben, nach dem ich sortieren möchte. Es ist ein bisschen nervig, dass ich es tun muss, aber solange Sie es früh tun, werden Sie wahrscheinlich keine Probleme haben.

In diesem Fall habe ich einen "View Counter" für Posts erstellt und wollte, dass Benutzer in der Lage sind, die am häufigsten gelesenen Posts zu sortieren. Auch hier sind Beiträge, die noch nie gesehen wurden (ich denke, das ist ziemlich unwahrscheinlich - aber immer noch), verschwunden, wenn nach Ansichtsanzahl sortiert wurde. Ich habe diesen Code hinzugefügt, um sicherzustellen, dass alle Beiträge eine Anzahl von Ansichten haben:

add_action('save_post', function ($postId) {
    add_post_meta($postId, '_sleek_view_count', 0, true);
});

Bitte zeigen Sie uns Ihren Code. Erleichtert die Beantwortung.
Kaiser

Erstens: meta_queryund tax_querysind immer ein, array( array() )da sie mehrere Arrays kombinieren. Zweitens - wie in meiner Antwort erwähnt - müssen Sie meta_value_numfür Zahlen verwenden. Es kann genauso gut erforderlich sein, um den Eintrag tatsächlich zu definieren meta_value_num(siehe WP_Query-Codex-Seiteneintrag). Zuletzt macht es keinen Sinn, orderin ASC und DESC Richtung zu gehen. Das ist doch nicht möglich. Der Raumbegrenzer funktioniert nur für orderbyund Sie können ihm nicht sagen, dass er den ersten ASCund den zweiten sortieren soll DESC. Dafür ist posts_clausesFilter da.
Kaiser

Und stellen Sie sicher, dass Ihre meta_value_numEingaben reelle Zahlen sind. Zu oft gesehen, dass jemand angibt, dass es sich um eine Zahl handelt, diese aber tatsächlich als Zeichenfolge in der Datenbank speichert.
Kaiser

Vielen Dank für Ihre Hilfe, ich werde dies versuchen und mich bei Ihnen melden. Der Grund dafür ASC DESCist, dass es nach meinem Kenntnisstand nach meta_valueIn ASCund dateIn sortiert DESC.
Powerbuoy

1
@Howdy_McGee das ist richtig. Einige meiner benutzerdefinierten Beitragstypen haben diesen Wert festgelegt. Manche nicht. Und die eingebauten Post-Typen (wie POST und PAGE) tun dies nicht. Wenn ich also versuche, nach diesem benutzerdefinierten Feld zu sortieren, werden nur Posts mit dem benutzerdefinierten Feld angezeigt.
Powerbuoy

Antworten:


4

Hierfür gibt es zwei mögliche Lösungen:

1. Alle Beiträge haben Meta

Die beste Lösung, die ich hier gefunden habe, besteht darin, den restlichen Artikeln / Produkten einen Artikelpreis von 0 zuzuweisen. Sie können dies manuell ausführen oder alle Artikel durchlaufen. Wenn der Preis leer ist, aktualisieren Sie ihn.

Um dies in Zukunft handhabbar zu machen, können Sie sich einbinden save_postund ihnen einen Wert zuweisen, wenn sie zum ersten Mal hinzugefügt werden (nur wenn dieser leer ist).

2. Mehrere Abfragen

Sie können die erste Abfrage währenddessen ausführen und die IDs der zurückgegebenen Posts speichern. Sie können dann eine weitere Abfrage für alle Posts und das Bestelldatum ausführen, ohne die IDs, die von der ersten Abfrage zurückgegeben werden.

Sie können dann die beiden Ergebnisse separat bestellen und Sie erhalten die gewünschten Ergebnisse.


1
Drei Jahre später hatte ich wieder das gleiche Problem: P Musste die save_postMethode verwenden (Ich habe meine Frage mit dem von mir verwendeten Code aktualisiert).
Powerbuoy

10

Easy Peasy, gerade 2018 getestet, wird derzeit in der Produktion verwendet.

$query->set( 'meta_query', array(
    'relation' => 'OR',
    array(
        'key' => 'custom_meta_key', 
        'compare' => 'EXISTS'
    ),
    array(
        'key' => 'custom_meta_key', 
        'compare' => 'NOT EXISTS'
    )
) );
$query->set( 'orderby', 'meta_value title' ); 

Hiermit wird nach allen Elementen mit und ohne Metaschlüssel gesucht, für die kein Wert angegeben wurde. Die Meta-Abfrage liefert zuverlässig den Schlüssel für die Bestellung. Es wurde getestet. Ich bin mir jedoch nicht sicher, wie es funktionieren wird, wenn die Meta-Abfrage mehrere Schlüssel verwendet.

Praktisches Beispiel

/**
 * Modifies query before retrieving posts. Sets the 
 * `meta_query` and `orderby` param when no `orderby` 
 * param is set, (default ordering).
 * 
 * @param   WP_Query  $query  The full `WP_Query` object.
 * @return  void
 */
function example_post_ordering( $query ) {

    // if not in wp-admin, 
    // and the query is the main query, 
    // and the query is not a singular query, 
    // and the query does not have an orderby param set...
    // Note: check for post types, etc. here as desired.
    if ( ! is_admin() 
    && $query->is_main_query() 
    && ! $query->is_singular() 
    && empty( $query->get( 'orderby' ) ) ) {

        // Setting just `meta_key` is not sufficient, as this 
        // will ignore posts that do not yet, or never will have 
        // a value for the specified key. This meta query will 
        // register the `meta_key` for ordering, but will not 
        // ignore those posts without a value for this key.
        $query->set( 'meta_query', array(
            'relation' => 'OR',
            array(
                'key' => 'custom_meta_key', 
                'compare' => 'EXISTS'
            ),
            array(
                'key' => 'custom_meta_key', 
                'compare' => 'NOT EXISTS'
            )
        ) );

        // Order by the meta value, then by the title if multiple 
        // posts share the same value for the provided meta key.
        // Use `meta_value_num` if the meta values are numeric.
        $query->set( 'orderby', 'meta_value title' );
    }

}

add_action( 'pre_get_posts', 'example_post_ordering', 10 );

Dadurch werden Beiträge custom_meta_keystandardmäßig sortiert und Beiträge ohne einen Wert für diesen Schlüssel nicht ignoriert.


Nur durch das Lesen des Codes, scheint alles, was zu tun ist, Beiträge zu bekommen, die haben custom_meta_keyund Beiträge bekommen, die nicht haben custom_meta_key. Fühlen Sie sich frei, ein aktuelles Arbeitsbeispiel in die Sortierung aufzunehmen.
Powerbuoy

1
Sie haben Recht, das ist alles, was es tut, aber die folgende Zeile ist für die Bestellung nach meta_value (des abgefragten Metaschlüssels) verantwortlich. $query->set( 'orderby', 'meta_value title' );(Nach Meta-Wert und dann nach Titel sortieren, wenn mehrere Beiträge den gleichen Wert für den Meta-Schlüssel haben.) Dies sollte im pre_get_postsHook mithilfe der übergebenen $queryVariablen erfolgen. Beachten Sie, dass die Frage lautete, wie nach Meta-Wert sortiert werden soll, während Posts, die keinen Wert für diesen Meta-Schlüssel haben, nicht ignoriert werden.
Noahmason

@powerbuoy Siehe aktualisiertes praktisches Beispiel
Noahmason

Okay, ich werde es versuchen, wenn ich das nächste Mal mit diesem Problem konfrontiert werde.
Powerbuoy

1
Arbeitete für mich in einem benutzerdefinierten get_posts()Aufruf, um Beiträge mit _featuredMeta nach oben zu schieben und danach nach Datum zu bestellen. Vielen Dank!
Natebeaty

8

Diese Methode gibt alle Posts zurück, einschließlich der mit und ohne den angeforderten. meta_keyBei der Bestellung werden jedoch merkwürdige Dinge ausgeführt.

add_action('pre_get_posts', 'my_stuff');
function my_stuff ($qry) {
    $qry->set(
        'meta_query',
        array(
            'relation' => 'OR', # Matches to this meta_query should be added to those matching the 'meta_key' query
            array(
                'key' => 'item_price', 
                'value' => 'bug #23268', 
                'compare' => 'NOT EXISTS'
            )
        )
    );

    $qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
    $qry->set('order', 'ASC DESC');
    $qry->set('meta_key', 'item_price');
}

Ich fand dies, indem ich mit all den verschiedenen Antworten auf diese Frage herumspielte und das generierte SQL durch Ausprobieren analysierte . Es scheint, dass das Festlegen von array('meta_query' => array('relation' => 'OR'))Ausgaben eine angemessene LEFT JOINOption INNER JOINist, um Posts einzuschließen, bei denen die Metadaten fehlen. Das Festlegen von NOT EXISTSverhindert, dass die WHEREKlausel Beiträge herausfiltert, denen das Metafeld fehlt. Für dieses spezielle WP_Queryist das generierte SQL (Einrückung / Zeilenumbruch hinzugefügt):

SELECT SQL_CALC_FOUND_ROWS
    wp_posts.ID
    FROM wp_posts
    INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
    INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id
    LEFT JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id AND mt1.meta_key = 'item_price')
    WHERE 1=1
    AND ( wp_term_relationships.term_taxonomy_id IN (2) )
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish'
        OR wp_posts.post_status = 'private')
    AND (wp_postmeta.meta_key = 'item_price'
        -- Oh look, here we give SQL permission to choose a random
        -- row from wp_postmeta when this particular post is missing
        -- 'item_price':
        OR  mt1.post_id IS NULL )
    GROUP BY wp_posts.ID
    ORDER BY wp_postmeta.meta_value,wp_posts.post_date DESC
    LIMIT 0, 10

Das Ergebnis ist eine Liste aller Beiträge mit meta_value von item_priceund Vermissten item_price. Alle der Pfosten mit item_pricekorrekt relativ zueinander bestellt werden, aber Beiträge fehlen item_pricewerden einige zufällige verwenden andere Meta - Wert (sagen wir, _edit_lastwas zu sein scheint 1für seine in der Datenbank oder eine andere interne Wordpress - Metadaten , die völlig willkürlich ist ziemlich oft) wp_postmeta.meta_valuein die ORDER BYKlausel. Während diese Methode nahe beieinander liegt und für bestimmte Daten zu funktionieren scheint, ist sie fehlerhaft. Alles, was ich sagen kann, ist, wenn Ihre item_priceWerte nicht mit den zufälligen Metafeldern in Konflikt stehen, die MySQL für die fehlenden Posts auswählt item_price, könnte dies für Sie in Ordnung sein. Wenn alles, was Sie brauchen, ist eine Garantie, dass Ihre Beiträge mititem_pricekorrekt in Bezug zueinander angeordnet sind, ohne Rücksicht auf die Anordnung anderer Beiträge, kann es in Ordnung sein. Aber ich denke, das ist nur ein Mangel in WordPress. Bitte korrigieren Sie mich, ich hoffe, ich liege falsch und es gibt einen Weg, dies zu beheben ;-).

Es scheint, dass INNER JOIN wp_postmetaMySQL für die eine zufällige Zeile aus mehreren postmetaZeilen auswählt, die dem Beitrag zugeordnet sind, wenn die meta_keyin dem angegebenen Beitrag fehlt. Aus SQL-Sicht müssen wir herausfinden, wie WordPress zur Ausgabe angewiesen wird ORDER BY mt1.meta_value. Diese Spalte ist im Gegensatz zu richtig, NULLwenn unsere angeforderte meta_keyfehlt wp_postmeta.meta_value. Wenn wir das tun könnten, würde SQL diese NULL(fehlenden Einträge) vor jedem anderen Wert sortieren und uns eine klar definierte Reihenfolge geben: Zuerst kommen alle Beiträge, denen das jeweilige Postmetafeld fehlt, und dann die Beiträge mit dem Feld. Aber das ist das ganze Problem: 'orderby' => 'meta_value'Kann sich nur beziehen 'meta_key' => 'item_price' und das Unausgeglichene wp_postmetaist immer ein INNER JOINstatt immer ein LEFT JOIN, Sinn wp_postmeta.meta_valueund wp_postmeta.meta_keykannniemals sein NULL.

Ich muss also sagen, dass dies mit WordPress nicht möglich ist, WP_Queryda es jetzt dokumentiert ist (in WordPress-3.9.1). Mühe. Wenn Sie dies also wirklich benötigen, um richtig zu funktionieren, müssen Sie sich wahrscheinlich an einer anderen Stelle in WordPress einbinden und die generierte SQL direkt ändern .


Sieht sehr vielversprechend aus! Ich werde es das nächste Mal versuchen, wenn ich dieses Problem habe. Ich möchte Ihnen die Antwort jetzt geben, möchte aber lieber bestätigen, dass sie zuerst für mich funktioniert.
Powerbuoy

Dies verhinderte, dass alles für mich auftauchte. Nach der Implementierung wurde nichts angezeigt.
Jake

@Jake Ja das gleiche hier. Hatte dieses Problem heute nochmal und habe es ausprobiert. Gibt 0 Ergebnisse zurück.
Powerbuoy

Welche Version von WordPress benutzt ihr? Ich denke, dieser Beitrag beschreibt die Verwendung einer internen, undokumentierten API, die von WordPress nicht unterstützt wird und daher wahrscheinlich nur funktioniert, wenn Sie WordPress-3.9.1 verwenden oder nicht zu viele Versionen darüber hinaus.
Binki

2

Ich denke ich habe eine Lösung.

Sie können zwei meta_keys verwenden, eine, die alle Beiträge haben (like "_thumbnail_id"), und die, die meta_keySie als Filter verwenden möchten.

Also deine Argumente:

$qry->set(
    'meta_query',
    array(
        'relation' => 'OR',
        array(
            'key' => 'item_price', 
            'value' => '', 
            'compare' => 'EXISTS'
        ),
        array(
            'key' => 'item_price', 
            'value' => '', 
            'compare' => 'EXISTS'
        )
    )
);

$qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
$qry->set('order', 'ASC DESC');
$qry->set('meta_key', 'item_price');

1
Das Problem hier ist der leere String-Vergleich, entfernen Sie es und es funktioniert 'value' => '', auch der zweite Vergleich sollte sein NOT EXISTSund die letzte gesetzte Anweisung ist nicht erforderlich
nodws

2

Das Problem, das jeder hier hat, hat mit der Reihenfolge der Meta-Abfragen zu tun. Um richtig zu sortieren, müssen Sie die Abfrage "NOT EXISTS" vor die Abfrage "EXISTS" setzen.

Der Grund dafür ist, dass WordPress den meta_value der letzten "LEFT JOIN" -Anweisung in der "ORDER BY" -Klausel verwendet.

Beispielsweise:

$pageQuery = new WP_Query([
    'meta_query' => [
        'relation' => 'OR',
        ['key' => 'item_price', 'compare' => 'NOT EXISTS'], // this comes first!
        ['key' => 'item_price', 'compare' => 'EXISTS'],
    ],
    'order' => 'DESC',
    'orderby' => 'meta_value_num',
    'post_status' => 'publish',
    'post_type' => 'page',
    'posts_per_page' => 10,
]);

1

Bei Bedarf können Sie jedes Mal, wenn ein Beitrag gespeichert oder aktualisiert wird, einen Standard-Metawert hinzufügen, wenn der Metawert nicht vorhanden ist.

function addDefaultMetaValue($post_id) {
    add_post_meta($post_id, 'item_price', 0, true);
}
add_action('save_post', 'addDefaultMetaValue');

Wenn Sie einen benutzerdefinierten Beitragstyp verwenden, ersetzen Sie den add_action('save_post', 'addDefaultMetaValue');durch add_action('save_post_{post_type}', 'addDefaultMetaValue');zadd_action('save_post_product', 'addDefaultMetaValue');


1

Ich hatte das Problem alleine für numerische Metawerte und wies darauf hin, dass es auch auf die Reihenfolge der Abfrage ankommt. Für mich muss die NOT EXISTSAbfrage die erste sein.

Beispiel:

$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_query', [
    'relation' => 'OR',
    [ 'key' => 'your_meta_name', 'compare' => 'NOT EXISTS' ],
    [
        'key' => 'your_meta_name',
        'compare' => 'EXISTS',
    ],
] );

Ebenfalls wichtig, um die richtige Richtung für numerische Werte zu erhalten, ist die allgemeine ’orderby’Einstellung ’meta_value_num’. Ansonsten haben Sie seltsame Ergebnisse für numerische Werte, zB:

1, 2, 20, 21, 3, 4, 5…

Anstatt:

1, 2, 3, 4, 5… 20, 21


1

Ich bin auch auf ein ähnliches Problem gestoßen und die folgende Lösung hat mir geholfen:

$args = array(
'post_type' => 'kosh_products',
'posts_per_page' => -1,
'meta_query' => array(
    'relation' => 'OR',
    'category_sort_order' => array(
        'key' => '_sort_order',
        'compare' => 'EXISTS'
    ),
    'category_sort_order_not_exists' => array(
        'key' => '_sort_order',
        'compare' => 'NOT EXISTS'
    ), 
),
'orderby' => array( 
    'category_sort_order' => 'ASC',
    'date' => 'ASC'
));
$query = new WP_Query( $args );

Ich habe auf WordPress Codex eine Beschreibung mit dem Titel " 'orderby' mit mehreren 'meta_key's " gefunden: https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters Bildbeschreibung hier eingeben


0

Dafür gibt es einen möglichen orderbyWert meta_value.

$query = new WP_Query( array ( 
    'meta_key'   => 'your_keys_name',
    'orderby'    => 'meta_value',
    'order'      => 'DESC',
    'meta_query' => array( array(
         'key'     => 'your_meta_key',
         'value'   => '',
         'compare' => 'NOT EXISTS',
         // 'type'    => 'CHAR',
    ) )
) );

Wenn Sie numerische Werte haben, verwenden Sie meta_value_numstattdessen einfach .

Haftungsausschluss: Dies ist nicht getestet, aber es sollte funktionieren. Punkt ist, dass Sie Ihre meta_keyund keyWerte angeben müssen . Ansonsten können Sie nicht mit nicht vorhandenen Werten vergleichen, wodurch es möglich sein sollte, beide Arten von Posts abzufragen. Es ist eine Art Hack-ish, aber solange es funktioniert ...


Vielen Dank für Ihre Antwort. Bitte überprüfen Sie meine aktualisierte Frage. Ich bin nicht sicher, ob ich Sie richtig verstanden habe.
Powerbuoy

Ich habe diese Arbeit immer noch nicht gemacht. Wenn Sie also eine Lösung haben, würde ich gerne wissen, was ich falsch mache. Außerdem setze ich ein Kopfgeld auf SO, wenn Sie es beanspruchen möchten: stackoverflow.com/questions/17016770/…
powerbuoy

1
Zwei Dinge. 'your_keys_name'und 'your_meta_key'sollten beide die gleiche Zeichenfolge sein, anstatt sich zu unterscheiden, sonst sieht es so aus, als hätten Sie die Frage falsch verstanden. Zweitens habe ich dies auf meinem lokalen Setup getestet und es werden alle Posts ausgeschlossen, bei denen der Schlüssel vorhanden ist (durch meta_query), und alle Posts, bei denen der Schlüssel fehlt (durch meta_key), was dazu führt, dass keine Posts angezeigt werden. Diese Antwort ist jedoch ein Schritt in Richtung etwas, das zumindest Worte ;-).
Binki

1
Oh, interessant, diese Antwort funktioniert , wenn man nur hinzufügen 'relation' => 'OR'zu meta_query. Verrücktes Zeug o_o.
Binki

@binki einfach eine Datei bearbeiten auf meine Frage und ändern sich die Bits denken Sie geändert werden sollte. Dies ist eine Community-gesteuerte Seite :)
Kaiser

0

Ich denke , was @kaiser versuchte , war zu tun , um die Abfrage zu sagen , alle Beiträge zurückzugeben, dass Meta - Schlüssel durch eine Art Dummy - Anwendung , wo Zustand zu nicht einem dieser Beiträge zu filtern. Wenn Sie also wissen, dass alle Werte, die Ihre benutzerdefinierten Felder annehmen können, x, y, z sind, können Sie sagen: "WHERE meta_key IN (x, y, z) ". Sie können dieses Problem jedoch vermeiden, indem Sie sagen:! = (' ') :

$query = new WP_Query( array ( 
    'orderby'    => 'meta_value_num',
    'order'      => 'DESC',
    'meta_query' => array( array(
         'key'     => 'item_price',
         'value'   => '',
         'compare' => '!=',
    ) )
) );

Auch nicht getestet, aber es scheint einen Versuch wert zu sein :-).


1
Kann das momentan nicht wirklich testen, aber ziemlich sicher, dass nur Posts zurückgegeben werden, bei denen item_price gesetzt ist und es nicht '' ist.
Powerbuoy

0

Ich habe das mit ein bisschen Hack (IMHO) umgangen, aber es hat in meinem Fall die Arbeit für mich erledigt.

Sie können die Filter posts_join_paged und posts_orderby verwenden , um die Verknüpfungs- und Ordnungszeichenfolgen zu aktualisieren. Auf diese Weise können Sie nach Belieben bestellen, solange Sie sich zuerst anmelden und nicht nach WP_Query, vorausgesetzt, das Feld muss für diesen bestimmten Beitrag vorhanden sein. Sie können dann entfernen Sie das meta_key, orderbyund `Bestellung von Ihrem WP_Query args.

Unten ist ein Beispiel. Am Anfang jeder Funktion musste ich für bestimmte Fälle aussteigen, da dies zu allem hinzugefügt wird, was WP_Query verwendet. Möglicherweise müssen Sie dies ändern, um es an Ihre speziellen Bedürfnisse anzupassen.

Die Dokumentation zu diesen beiden Filtern fehlt leider so ... viel Glück! :)

add_filter('posts_join_paged', 'edit_join', 999, 2);
add_filter('posts_orderby', 'edit_orderby', 999, 2);

/**
 * Edit join
 *
 * @param string $join_paged_statement
 * @param WP_Query $wp_query
 * @return string
 */
function edit_join($join_paged_statement, $wp_query)
{
    global $wpdb;
    if (
        !isset($wp_query->query)
        || $wp_query->is_page
        || $wp_query->is_admin
        || (isset($wp_query->query['post_type']) && $wp_query->query['post_type'] != 'my_custom_post_type')
    ) {
        return $join_paged_statement;
    }

    $join_to_add = "
        LEFT JOIN {$wpdb->prefix}postmeta AS my_custom_meta_key
            ON ({$wpdb->prefix}posts.ID = my_custom_meta_key.post_id
                AND my_custom_meta_key.meta_key = 'my_custom_meta_key')
    ";

    // Only add if it's not already in there
    if (strpos($join_paged_statement, $join_to_add) === false) {
        $join_paged_statement = $join_paged_statement . $join_to_add;
    }

    return $join_paged_statement;
}

/** 
 * Edit orderby
 *
 * @param string $orderby_statement
 * @param WP_Query $wp_query
 * @return string
 */
function edit_orderby($orderby_statement, $wp_query)
{
    if (
        !isset($wp_query->query)
        || $wp_query->is_page
        || $wp_query->is_admin
        || (isset($wp_query->query['post_type']) && $wp_query->query['post_type'] != 'my_custom_post_type')
    ) {
        return $orderby_statement;
    }

    $orderby_statement = "my_custom_meta_key.meta_value DESC";

    return $orderby_statement;
}

Der Code funktioniert. Der meta_value wird jedoch als String behandelt. 6 wird also mit 50 bewertet. Sind Änderungen möglich, um sie als Zahlen zu behandeln?
Drivingralle

@Drivingralle cast(my_custom_meta_key.meta_value as unsigned) DESCsollte den Trick tun ...
2.

1
Danke @tfrommen. $orderby_statement = "cast(my_custom_meta_key.meta_value as unsigned) DESC";funktioniert super.
Drivingralle

0

Diese Lösung hat bei mir funktioniert:

add_action( 'pre_get_posts', 'orden_portfolio' );
function orden_portfolio( $query ) {

    if( ! is_admin() ) {

        $query->set( 'orderby', 'meta_value_num' );
        $query->set( 'order', 'ASC' );
        $query->set( 'meta_query', [
            'relation' => 'OR',
            [ 
                'key' => 'ce_orden', 
                'compare' => 'NOT EXISTS' ],
            [
                'key' => 'ce_orden',
                'compare' => 'EXISTS',
            ],
        ] );

        return $query;

    }

}

Diese Lösung zeigt jedoch zuerst die Datensätze mit null meta_value an. Diese andere Lösung zeigt ASC-Reihenfolge und Nullen am Ende:

function custom_join($join) {
    global $wpdb;

    if( ! is_admin() ) {
        $join .= $wpdb->prepare(
        ' LEFT JOIN ' . $wpdb->postmeta . ' cpm ON cpm.post_id = ' . $wpdb->posts . '.ID AND cpm.meta_key = %s'
        , 'ce_orden' );
    }

    return $join;
}

add_filter('posts_join','custom_join');

function custom_orderby($orderby_statement){
    global $wpdb;

    if ( ! is_admin() ) {
        $orderby_statement = "CAST( COALESCE(cpm.meta_value,99999) as SIGNED INTEGER) ASC";
    }

    return $orderby_statement;
}

add_filter('posts_orderby','custom_orderby', 10, 2 ); 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.