Wie kann ich eine meta_query mit einem Array als meta_field erstellen?

16

Hier sind die Argumente für meine Anfrage:

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports',
        )
    )
);

Dies funktioniert, wenn topicses sich um eine Zeichenfolge handelt, nicht jedoch, wenn es sich um ein Array handelt. Ich möchte, dass diese Abfrage funktioniert, wenn dies beispielsweise der Fall topicsistarray( 'sports', 'nonprofit', etc. )

Gibt es eine Möglichkeit, Metaabfragen mit Arrays als meta_key zu erstellen?

mike23
quelle
Bitte klarstellen - meinst du, dass der gespeicherte Wert von "topics" ein Array ist? Oder dass der gespeicherte Wert eine Zeichenfolge ist und Sie mehrere Begriffe an die Abfrage in einem Array übergeben möchten?
MathSmath
@MathSmath, ich meine, dass der gespeicherte Wert ein Array ist.
mike23

Antworten:

30

Füttert die Abfrage mit einem Array möglicher Werte

Wenn der Wert in der Datenbank eine Zeichenfolge ist und Sie der Abfrage mehrere Werte hinzufügen möchten:

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => array ( 'sports', 'nonprofit', 'community' ),
            'compare' => 'IN'
        )
    )
);

Suchen nach einem bestimmten Wert in einem serialisierten Datenfeld

Wenn der Wert in der Datenbank ein Array mit mehreren Themen ist und Sie nach einem einzelnen Thema in diesem Array suchen möchten (Beachten Sie, dass ein Array in der Datenbank als solches abgerufen werden kann, sich jedoch in der Datenbank in serialisierter Form befindet, d. H Zeichenfolge auch):

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports',
            'compare' => 'LIKE'
        )
    )
);

Die Verwendung von 'LIKE' als Vergleichswert ist nicht so eindeutig, wie Sie es sich erhofft haben, aber die beste Option.

Daneben besteht Ihre einzige andere Möglichkeit darin, alle Posts mit den festgelegten meta_key "topics" abzurufen und manuell zu durchlaufen oder, mit anderen Worten, den Wert in der Schleife zu überprüfen und die Posts unter dieser Bedingung anzuzeigen.

Johannes Pille
quelle
13

Um von Johannes 'Antwort abzuweichen, da es sich um ein serialisiertes Array handelt, müssen Sie möglicherweise etwas anders damit umgehen, wenn Sie etwas wie Benutzer-IDs speichern (was in meinem Fall der Fall war).

Post-Meta wurde gespeichert wie:

array( "1", "23", "99");

Also ja, sie sind ganze Zahlen, aber durch update_post_metasie wurden sie als Zeichenfolgen gerettet.

'meta_query' => array(
            array(
                    'key'     => 'my_meta_key',
                    'value'   => serialize( strval( 1 ) ),
                    'compare' => 'LIKE'
                )
            )

Also machen Sie tatsächlich einen LIKE-Vergleich mit der serialisierten String-Version von dem, was Sie suchen. Ich habe ein paar gute Stunden damit verbracht, so etwas zum Laufen zu bringen, und bis jetzt war dies das Beste, was ich mir einfallen lassen konnte.

sMyles
quelle
serialize (strval (1)) löste mein Problem, Danke
Behzad
Kam heute zufällig auf diese alte Antwort. Ich mag deine Hinzufügung. +1
Johannes Pille
Ich bin auch darauf gestoßen, mein Ding ist, dass ich alle Posts bekommen muss, bei denen user_id nicht im Array ist, aber die obige Lösung funktioniert nicht, also habe ich es so gemacht: 'meta_query' => array( array( 'key' => 'my_meta_key', 'value' => ':' . $user_id . ';', 'compare' => 'NOT LIKE' ) ) Denn wenn serialisiert, werden alle Werte wie folgt gespeichert: ' :Wert;'
Bobz
4

Eine weitere leichte Verbesserung gegenüber der Antwort von @sMyles.

Ich hatte Fälle, in denen IDs sowohl als Zeichenfolgen (z. B. aus einer Formulareingabe) als auch als Ganzzahlen (z update_post_meta($post_id, authorized_users', array(get_current_user_id()));. B. ) gespeichert wurden . Dies ähnelt dem bekannten Problem, bei wp_set_object_terms()dem Sie Term-IDs verwenden können, um die Termini festzulegen. Wenn Sie sie jedoch nicht zuerst als Ganzzahlen umwandeln, haben Sie eine Chance von etwa 50%, neue Termini mit diesen Zahlen als Namen zu erstellen stattdessen.

Dies kann dazu führen, dass sie in einem serialisierten Array ganz anders gespeichert werden, wie aus den Auszügen eines solchen Falls aus der Datenbank meiner Testwebsite ersichtlich ist:

a:1:{i:0;s:1:"1";} // 's' for 'string', also note the double quotes
a:1:{i:0;i:1;} // 'i' for 'integer', no quotes

Beide oben genannten Optionen print_r()werden bei Durchspeisung als gerendert

Array
(
    [0] => 1
)

Um dies zu beheben, habe ich eine kleine Änderung an der Abfrage vorgenommen, meta_queryindem ich eine relationund eine andere Version der Abfrage hinzugefügt habe , die den Wert als Ganzzahl anstelle einer Zeichenfolge umwandelt.

Hier ist das Endergebnis:

        'meta_query' => array(
            'relation' => 'OR', // Lets it know that either of the following is acceptable
            array(
                'key' => 'bcm_enm_authorized_users',
                'value'   => serialize(strval(get_current_user_id())), // Saved as string
                'compare' => 'LIKE'
            ),
            array(
                'key' => 'bcm_enm_authorized_users',
                'value'   => serialize(intval(get_current_user_id())), // Saved as integer
                'compare' => 'LIKE'
            ),
        ),

BEARBEITEN: Ich habe gerade festgestellt, dass diese Methode das Risiko von Kollisionen mit Array-Indizes birgt, die es jemandem ermöglichen können, illegal auf Materialien zuzugreifen, wenn sie nicht im Array enthalten sind, aber ihre Benutzer-ID als Index angezeigt wird. Während dies funktioniert, sollten Sie sicherstellen, dass alle zu suchenden Werte vor dem Speichern als Zeichenfolgen umgewandelt werden, damit Sie stattdessen die @ sMyles-Methode verwenden können.

Kaji
quelle
Dies sollte die gewählte und zuverlässigste Antwort sein
Amin
2

Ich würde Johannes 'Antwort annehmen. Ich möchte dies jedoch verbessern, da Sie mit dieser meta_query einen Fall wie diesen treffen werden

Ihr Wert ist

array('sports','movies', 'sports2');

wenn du suchst

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports',
            'compare' => 'LIKE'
        )
    )
);

dann wird das Ergebnis sowohl 'sport' als auch 'sport2' zurückgeben.

Um dies zu beheben, ändern Sie die Argumente für meta_query in

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports";',
            'compare' => 'LIKE'
        )
    )
);

Dies liegt daran, dass der Wert in der Datenbank serialisiert ist und jedes Element durch ein Semikolon getrennt wird. Somit funktionieren die obigen Argumente

Wenn es sich bei den Elementen im Wert um Zahlen handelt, müssen Sie nur das doppelte Anführungszeichen entfernen. "

$args = array(
        'post_type' => 'news',
        'meta_query' => array(
            array(
                'key' => 'topics',
                'value' => '1;',
                'compare' => 'LIKE'
            )
        )
    );
Ha Doan Ngoc
quelle
1

Ich habe heute mit etwas Ähnlichem gekämpft. Ich muss ein ACF-Beziehungsfeld (Advanced Custom Fields) mit mehreren verbundenen Benutzern (Array) abfragen.

Nach der Aktualisierung des Feldes über PHP funktionierte die Abfrage nicht. Nach dem Update über die ACF-Benutzeroberfläche funktionierte die Abfrage.

Das Problem war, dass mein PHP-Code die Beziehungswerte auf int-Werte und die Benutzeroberfläche auf string-Werte setzte. Um sicherzustellen, dass beide funktionieren, verwende ich diese Abfrage jetzt (hier im Beispiel):

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key' => 'topics',
            'value' => '1;',  // works for int-array
            'compare' => 'LIKE'
        ),
        array(
            'key' => 'topics',
            'value' => '"1"',  // works for string-array
            'compare' => 'LIKE'
        ),
    )
);
Julian Stark
quelle