Comment créer une méta_query avec un tableau sous la forme meta_field?

12

Voici les arguments de ma requête:

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

Cela fonctionne lorsque topics est une chaîne, mais pas lorsqu'il s'agit d'un tableau. J'aimerais que cette requête fonctionne lorsque topics est par exemple array( 'sports', 'nonprofit', etc. )

Est-il possible de créer des méta-requêtes avec des tableaux sous forme de méta_key?

    
posée mike23 15.06.2012 - 15:04

5 réponses

22

Alimentation de la requête d'un tableau de valeurs possibles

Si la valeur de la base de données est une chaîne et que vous souhaitez alimenter la requête en plusieurs valeurs:

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

Recherche d'une valeur spécifique dans un tableau de données sérialisé

Si la valeur de la base de données est un tableau de plusieurs sujets et que vous souhaitez rechercher un seul sujet dans ce tableau (notez qu'un tableau de la base de données peut être récupéré en tant que tel, mais qu'il réside dans un formulaire en série qui est aussi une chaîne):

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

Utiliser 'LIKE' comme valeur de comparaison n'est pas une instruction aussi claire que vous l'auriez espéré, mais c'est la meilleure option à utiliser.

À côté de cela, votre seule autre option serait de récupérer toutes les publications qui ont la meta_key "topics" et de les parcourir manuellement, ou, en d'autres termes, de rechercher la valeur dans la boucle et affichez les messages sur cette condition.

    
réponse donnée Johannes Pille 15.06.2012 - 16:27
11

Pour interrompre la réponse de Johannes, comme il s’agit d’un tableau sérialisé, si vous stockez quelque chose comme l’identité de l’utilisateur (ce qui était mon cas), vous devrez peut-être le traiter un peu différemment.

La méta de publication a été enregistrée comme:

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

Alors oui, ce sont des entiers, mais ils ont été enregistrés sous forme de chaînes via update_post_meta .

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

Vous faites donc une comparaison similaire à la version chaîne sérialisée de ce que vous recherchez. J'ai passé de bonnes heures à essayer d'obtenir ce genre de chose et jusqu'à présent, c'était le meilleur que je pouvais trouver.

    
réponse donnée sMyles 06.06.2015 - 05:09
2

Une autre légère amélioration par rapport à la réponse de @sMyles.

J'ai eu des cas où les identifiants ont été stockés à la fois sous forme de chaînes (comme lorsqu'elles sont extraites d'une entrée de formulaire) et sous forme d'entiers (par exemple, update_post_meta($post_id, authorized_users', array(get_current_user_id())); ). C'est un peu comme le problème bien connu avec wp_set_object_terms() où vous pouvez utiliser des identifiants de termes pour définir les termes, mais si vous ne les exprimez pas en tant qu'entiers, vous avez environ 50% de chances de créer de nouveaux termes avec ces nombres. comme leurs noms à la place.

Cela peut entraîner leur stockage très différemment dans un tableau sérialisé, comme le montrent les extraits d'un tel cas de la base de données de mon site de test:

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

Les deux éléments ci-dessus, lorsqu'ils seront alimentés via print_r() , seront rendus sous la forme

Array
(
    [0] => 1
)

Pour résoudre ce problème, j’ai légèrement modifié le meta_query en ajoutant un relation et une autre version de la requête qui convertit la valeur sous la forme d’un entier au lieu d’une chaîne.

Voici le résultat final:

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

EDIT: vient de réaliser que cette méthode risquait de provoquer des collisions avec des index de tableau, ce qui pourrait permettre à une personne d'accéder illégalement à des matériaux s'ils ne se trouvaient pas dans le tableau, Un index. En tant que tel, bien que cela fonctionne si le problème est discuté, il est préférable de s’assurer que les valeurs que vous souhaitez rechercher sont converties en chaînes avant de les enregistrer, afin que vous puissiez utiliser la méthode de @sMyles. à la place.

    
réponse donnée Kaji 13.07.2018 - 04:44
1

Je voudrais aller pour la réponse de Johannes. Cependant, je veux améliorer cela car en utilisant cette meta_query, vous rencontrerez un cas comme celui-ci

votre valeur est

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

lorsque vous effectuez une recherche

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

alors le résultat retournera 'sport' et 'sport2'.

Pour résoudre ce problème, remplacez les arguments meta_query par

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

C'est parce que la valeur est sérialisée dans la base de données et que chaque élément sera séparé par un point-virgule. Ainsi, les arguments ci-dessus fonctionneront

Si les éléments de la valeur sont numériques, il vous suffit de supprimer le guillemet double "

$args = array(
        'post_type' => 'news',
        'meta_query' => array(
            array(
                'key' => 'topics',
                'value' => '1;',
                'compare' => 'LIKE'
            )
        )
    );
    
réponse donnée Ha Doan Ngoc 02.11.2016 - 09:22
0

J'ai eu un problème avec quelque chose de similaire aujourd'hui. Je dois interroger un champ de relation ACF (Advanced Custom Fields) avec plusieurs utilisateurs associés (tableau).

Après la mise à jour du champ via php, la requête ne fonctionnait pas. Après la mise à jour via l'interface utilisateur ACF, la requête a fonctionné.

Le problème était que mon code php définissait les valeurs de relation comme étant des valeurs int et que l'interface utilisateur le définissait comme des valeurs de chaîne. Pour m'assurer que les deux fonctionnent, j'utilise cette requête maintenant (adapté à l'exemple ici):

$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'
        ),
    )
);
    
réponse donnée Julian Stark 06.07.2018 - 08:22

Lire d'autres questions sur les étiquettes