Meta consulta con valor booleano verdadero / falso

11

Estoy tratando de mostrar todas las propiedades de alquiler, primero por todas las propiedades que no se han alquilado, y luego por todas las propiedades que se alquilan actualmente. Hay un tipo de publicación personalizada 'rent' con meta de publicación personalizada para el precio alquilado (_price_rented) que es una casilla de verificación (devuelve verdadero o falso ... verdadero si se ha alquilado). Necesito cambiar la consulta para mostrar todas las propiedades con las propiedades disponibles (no alquiladas) que aparecen primero y luego las propiedades alquiladas.

Aquí está mi consulta:

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

Por alguna razón, esta consulta muestra todas las propiedades que SE HAN alquilado. Cuando cambio el valor de 'falso' a 'verdadero' en meta_query, no muestra ninguna propiedad.

Entonces, pensé, el valor de retorno es falso (para propiedades que SE ALQUILAN) o NULL (para propiedades que NO se alquilan), pero no estoy seguro de cómo consultar un resultado NULL (no falso), agregué un ' compare 'argumento con meta_query y establezca el valor en'! = 'pero tampoco funcionó.

EDITAR: var_dump devuelve lo siguiente para un apartamento disponible, no alquilado: string(0) ""y para un apartamento no disponible, alquilado:string(1) "1"

Kegan Quimby
fuente
utilizando los valores 1 y 0 tal vez?
reikyoushin
meta_query type => string. Los valores posibles son 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'. El valor predeterminado es 'CHAR'.
iEmanuele
@reikyoushin: el uso de un '1' devuelve todas las propiedades alquiladas y un '0' no devuelve ninguna propiedad.
Kegan Quimby
1
@iEmanuele: cambiar eso parece no tener efecto (pensé lo mismo). Lo vi en este artículo: thethemefoundry.com/blog/…
Kegan Quimby
1
¿Está _price_rentedconfigurado para ambos truey falsevalores, o solo está configurado para true? Consulte la base de datos por favor. Pregunté porque no se pasa ninguna casilla de verificación sin marcar, por POSTlo que me pregunto si el valor está establecido para esos casos.
s_ha_dum

Respuestas:

4

WP_Meta_Query es una parte de alguna manera "no tan estable" en el núcleo y si no prestas mucha atención, puede fácilmente ser confundido.

Cuando está haciendo ay new WP_Query()tiene meta_query => array()argumentos o sus pares equivalentes de clave / valor, luego new WP_Meta_Query()salta, instantáneamente seguido de análisis.

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

Valores permitidos

Cuando consulta metadatos, entonces hay una boolopción. Y si lo usara, entonces recurriría a CHAR, cuyo valor predeterminado como la matriz de valores permitidos es:

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

donde NUMERICse restablecerá a SIGNED.

Depuración

Existen numerosos filtros que pueden afectar el proceso de guardado posterior, por lo que lo primero que debe hacer es verificar los diferentes valores dentro de algún bucle:

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

Luego, dependiendo del valor de retorno, deberá usar SIGNED, si el resultado es 0o 1, "true"o "false"si el resultado es una cadena. Si realmente es booleano, aún sugeriría usar stringsolo para asegurarse de que pase $GLOBALS['wpdb'], que solo puede pasar %scadenas y %ddígitos.

Notas adicionales

Como acabo de ser informado de la entrada del Codex para elWP_Meta_Query día de hoy, he visto que hay un montón de diferentes salidas (la adición de numerosas cantidades de que no sean necesarios JOINS, que se discuten en Trac aquí y aquí con fuera un solo parche movido en el núcleo) posible. (Ticket de seguimiento para las ANDpartes aquí ) El punto es que es posible usar una combinación de meta_*argumentos junto con la meta_querymatriz y sus submatrices. El resultado es bastante desconocido a menos que lo descargue , por lo que en mi humilde opinión , es mejor usar una u otra forma de agregar entradas. Especialmente cuando solo eresutilizando meta_key, ya que esto da como resultado una "consulta de solo clave" en algunos casos.

Solución

Como se señala en los comentarios:

(...) var_dumpdevuelve lo siguiente para un apartamento no alquilado disponible: string(0) ""y para un apartamento alquilado no disponible:string(1) "1"

Ahora el meta_querytiene que usar

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

Si desea obtener los "apartamentos alquilados no disponibles" o utilizar '!='para recuperar los apartamentos "no alquilados".

Nota: Los valores posibles para meta_compareson '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'NOT EXISTS', 'REGEXP', 'NOT REGEXP'o 'RLIKE'. El valor por defecto es '='.

emperador
fuente
3

Me enfrenté al mismo problema y después de una hora de búsqueda encontré el "NOT EXISTS"y "EXISTS"valor ( only in WP >= 3.5 ). Por lo tanto, no es necesario solicitar un metavalor, solo verifique si existe la meta_key:

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

Me está funcionando perfectamente.

Thibaut
fuente
3

TL; DR: este problema probablemente ocurre principalmente cuando se crea un campo booleano como opcional. Puede solucionarlo haciendo que sea necesario o utilizando una consulta más compleja para recuperar el caso predeterminado.

Más detalles:

Aquí hay dos problemas de representación de datos: uno es qué valores de datos se utilizan para representar verdadero / falso y el otro es si el campo se está almacenando o no si es el valor predeterminado (generalmente falso).

Parte 1: Miré el SQL generado por las WP_Meta_Querycomparaciones entre verdadero y falso, y descubrí que para verdadero sustituye '1' y falso '' (la cadena vacía). Entonces, lo que escriba en la base de datos debe estar de acuerdo con eso si va a hacer consultas en comparación con los valores reales verdaderos y falsos. En particular, no desea escribir '0' para falso. En su lugar, podría ser más infalible escribir y probar para 0 y 1 (y muchos creadores de formularios lo hacen). Pero verifique lo que se está escribiendo en la base de datos y tenga esto en cuenta al crear su consulta.

Parte 2: Suponiendo que falso es el valor predeterminado, es fácil encontrar registros cuyo valor sea verdadero:

... 'meta_key' => 'my_key', 'meta_value' => 1 (o cierto)

Pero el otro lado es desafiante: puede haber un valor falso o puede que no haya ningún valor. Esto puede suceder si el valor se incluyó como opcional en un formulario --- entonces, mientras el usuario no lo establezca o lo cambie explícitamente, no se agregará a la base de datos. Tenga en cuenta que si solo lo está utilizando get_post_meta, funcionará bien de esta manera: devolver un valor falso y no devolver ningún valor logrará lo mismo.

Pero cuando estás usando WP_Query, no es tan fácil. (O si es así, aún no he descubierto cómo).

Tienes dos (o quizás tres) opciones:

  1. Asegúrese de que el campo siempre se inicializa explícitamente a un valor real. En algunos creadores de formularios, puede hacer esto haciendo que el campo sea obligatorio y dándole un valor predeterminado. Entonces puedes probar de ...'meta_value' => 0 manera confiable.

  2. Haga dos consultas, la primera que prueba un valor falso y la segunda que no prueba ningún valor. Estos se pueden combinar en una sola WP_Query como esta:

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

Probablemente esta no sea una consulta eficiente. Dependiendo de muchos factores, podría ser mejor devolver todos los objetos y filtrarlos en su propio código.

  1. Es posible usar 'sin valor' para significar falso. Para hacer esto, siempre que el valor se establezca en falso, debe eliminar el metavalor en lugar de actualizarlo .

En ese caso, una sola 'NOT EXISTS'consulta devolverá de forma confiable los objetos correctos. (No creo que muchos creadores de formularios o complementos admitan este comportamiento, por lo que solo lo usaría en código puramente personalizado).

Denise Draper
fuente