web-dev-qa-db-fra.com

Méta requête avec valeur booléenne true/false

J'essaie de montrer toutes les propriétés locatives, d'abord par toutes les propriétés qui n'ont pas été louées, puis par toutes les propriétés actuellement louées. Il existe un type de message personnalisé "rent" avec une méta personnalisée pour le prix loué (_price_rented) qui est une case à cocher (renvoie vrai ou faux ... vrai s'il a été loué). Je dois modifier la requête pour afficher toutes les propriétés avec les propriétés disponibles (non louées) apparaissant en premier, puis les propriétés louées apparaissant.

Voici ma requête:

$ts_properties = new WP_Query( 
    array( 
    'post_type' => 'rent', 
    'paged' => $paged, 
    'posts_per_page' => -1,
    'meta_key' => '_price_rented',
    'orderby' => 'meta_value',
    'order' => 'DESC',
    'meta_query' => array(
        array(
        'key' => '_price_rented',
        'value' => false,
        'type' => 'BOOLEAN',
        ),
    ) 
) 
);

Pour une raison quelconque, cette requête affiche toutes les propriétés qui ont été louées. Lorsque je mets la valeur de "false" à "true" dans la méta_query, elle n'affiche aucune propriété.

Alors, j'ai alors pensé que la valeur de retour est soit false (pour les propriétés louées), soit NULL (pour les propriétés non louées), mais je ne suis pas sûr de savoir comment demander un résultat NULL (pas false), j'ai ajouté un ' compare 'argument à meta_query et définit la valeur sur'! = 'mais cela ne fonctionne pas non plus.

EDIT: var_dump retourne ce qui suit pour un appartement disponible non loué: string(0) "" et pour un appartement non disponible, loué: string(1) "1"

8
Kegan Quimby

J'ai rencontré le même problème et après une heure de recherche, j'ai trouvé le "NOT EXISTS" et le "EXISTS" valeur ( only in WP >= 3.5 ). Donc pas besoin de demander une méta-valeur, il suffit de vérifier si la méta_key existe:

'meta_key'     =>   '_price_rented'  ,
'meta_compare' =>   'NOT EXISTS'     ,

Cela fonctionne parfaitement pour moi.

3
Thibaut

WP_Meta_Query est en quelque sorte "pas si stable" dans le noyau et si vous ne payez pas beaucoup d’attention, il est facile de rompre avec la confusion.

Lorsque vous effectuez une opération new WP_Query() et que vous avez des arguments meta_query => array() ou ses équivalents paire/clé uniques, alors new WP_Meta_Query() intervient, suivi instantanément par une analyse.

$this->meta_query = new WP_Meta_Query();
$this->meta_query->parse_query_vars( $q );

Valeurs autorisées

Lorsque vous interrogez des métadonnées, il existe une option bool. Et si vous l'utilisiez, il tomberait alors dans CHAR, dont la valeur par défaut comme tableau des valeurs autorisées est:

'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'

NUMERIC sera réinitialisé à SIGNED.

Débogage

De nombreux filtres peuvent affecter le processus de post-sauvegarde. La première chose à faire est donc de vérifier les différentes valeurs dans une boucle:

var_dump( get_post_meta( get_the_ID(), '_price_rented', true ) );

Ensuite, en fonction de la valeur de retour, vous devrez soit utiliser SIGNED, si le résultat est 0 ou 1, ou "true" ou "false" si le résultat est une chaîne. Si c'est vraiment booléen, je suggérerais quand même d'utiliser string uniquement pour s'assurer qu'il passe $GLOBALS['wpdb'], qui ne peut que transmettre %s chaîne et %d chiffre.

Notes complémentaires

Comme je viens de mettre à jour l’entrée du Codex pour WP_Meta_Query aujourd’hui, j’ai vu qu’il existait une multitude de sorties (en ajoutant de nombreuses quantités de JOINS inutiles, qui sont discutées sur Trac ici et ici avecen dehors un seul patch déplacé dans le noyau) possible. (Ticket de suivi pour AND parts here ) Le fait est qu'il est estpossible d'utiliser une combinaison d'arguments meta_* à côté du tableau meta_query et de ses sous-tableaux. Le résultat est pratiquement inconnu à moins que vous ne le sauvegardiez, donc IMHOvous feriez mieux d’utiliser soit le ou l’autre façon d’ajouter des entrées. Surtoutlorsque vous êtes seulementen utilisant meta_key, comme il en résulte une "requête clé uniquement" dans certains cas.

Solution

Comme indiqué dans les commentaires:

(...) var_dump retourne ce qui suit pour un appartement disponible non loué: string(0) "" et pour un appartement non disponible, loué: string(1) "1"

Maintenant, le meta_query doit utiliser

'meta_query' => array( 'relation' => 'OR', array(
    'meta_key'     => '_price_rented',
    'meta_value'   => '1',
    'meta_compare' => '='
) );

Si vous souhaitez obtenir les "appartements non disponibles, loués" ou utilisez '!=' pour récupérer les appartements "non loués".

Remarque: les valeurs possibles pour meta_compare sont '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'NOT EXISTS', 'REGEXP', 'NOT REGEXP' ou 'RLIKE'. La valeur par défaut est '='.

3
kaiser

TL; DR: Ce problème se produit probablement lorsqu'un champ booléen est créé de manière facultative. Vous pouvez résoudre ce problème en le rendant obligatoire ou en utilisant une requête plus complexe pour récupérer le cas par défaut.

Plus de détails:

Deux problèmes de représentation des données se posent ici: le premier concerne les valeurs de données utilisées pour représenter la valeur vrai/faux et le second consiste à savoir si le champ est stocké ou non s'il s'agit de la valeur par défaut (généralement false).

Partie 1: J'ai regardé le SQL généré par WP_Meta_Query pour des comparaisons entre vrai et faux, et trouvé que pour vrai, il substitue '1' et pour faux '' (la chaîne vide). Donc, tout ce que vous écrivez dans la base de données doit être en accord avec celui-ci si vous allez faire des requêtes en comparant les valeurs réelles vraies et fausses. En particulier, vous ne voulez pas écrire "0" pour faux. Il serait peut-être plus sûr d’écrire et de tester 0 et 1 à la place (et de nombreux constructeurs de formulaires le font). Mais vérifiez ce qui est écrit dans la base de données et gardez cela à l’esprit lors de la création de votre requête.

Partie 2: En supposant que false est la valeur par défaut, il est facile de rechercher les enregistrements dont la valeur est true:

... 'meta_key' => 'my_key', 'meta_value' => 1 (ou true)

Mais l’autre côté est un défi: il peut y avoir une fausse valeur, voire aucune valeur. Cela peut arriver si la valeur a été listée comme optionnelle dans un formulaire --- tant que l'utilisateur ne la définit pas explicitement ou ne la modifie pas, elle ne sera pas ajoutée à la base de données. Notez que si vous n'utilisez que get_post_meta, cela fonctionnera parfaitement: renvoyer une valeur fausse et ne renvoyer aucune valeur donnera le même résultat.

Mais lorsque vous utilisez WP_Query, ce n'est pas si facile. (Ou si c'est le cas, je n'ai pas encore compris comment).

Vous avez deux (ou peut-être trois) options:

  1. Assurez-vous que le champ est toujours explicitement initialisé à une valeur réelle. Pour ce faire, vous créez le champ obligatoire et lui attribuez une valeur par défaut. Ensuite, vous pouvez tester ...'meta_value' => 0 de manière fiable.

  2. Faites deux requêtes, la première qui teste une valeur fausse et la seconde qui teste aucune valeur. Ceux-ci peuvent être combinés dans un seul WP_Query comme ceci:

    meta_query => {
        relation => 'OR'
        array(
            'key'     => 'my_key',
            'value'   => 0,
            'compare' => '='
        ),
        array(
            'key'     => 'my_key',
            'compare' => 'NOT EXISTS',
        ),
    )
    

Ce n'est probablement pas une requête efficace. En fonction de nombreux facteurs, il peut être préférable de renvoyer tous les objets et de les filtrer dans votre propre code.

  1. Il est possible d'utiliser 'aucune valeur' ​​pour signifier faux. Pour ce faire, chaque fois que la valeur doit être définie sur false, vous devez supprimer la méta-valeur au lieu de updated it.

Dans ce cas, une seule requête 'NOT EXISTS' renverra de manière fiable les objets appropriés. (Je ne pense pas que beaucoup de constructeurs de formulaires ou de plugins prennent en charge ce comportement. Je ne l'utiliserais donc que dans du code purement personnalisé.)

2
Denise Draper