Meta query con valor booleano true/false

31 jul 2013, 18:23:12
Vistas: 33.7K
Votos: 18

Estoy intentando mostrar todas las propiedades de alquiler, primero mostrando las propiedades que no han sido alquiladas, y luego las que están actualmente alquiladas. Hay un tipo de post personalizado 'rent' con un meta post personalizado para el precio alquilado (_price_rented) que es un checkbox (devuelve true o false... true si HA sido alquilado). Necesito modificar la consulta para mostrar todas las propiedades con las disponibles (no alquiladas) apareciendo 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 HAN sido alquiladas. Cuando cambio el valor de 'false' a 'true' en la meta_query, no muestra ninguna propiedad.

Entonces pensé que el valor devuelto es false (para propiedades que ESTÁN alquiladas) o NULL (para propiedades que NO están alquiladas), pero no estoy seguro de cómo consultar un resultado NULL (no false). Agregué un argumento 'compare' a la meta_query y establecí el valor en '!=' pero tampoco funcionó.

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

11
Comentarios

¿usando valores 1 y 0 quizás?

reikyoushin reikyoushin
31 jul 2013 18:24:55

meta_query type => cadena. Los valores posibles son 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'. El valor por defecto es 'CHAR'.

iEmanuele iEmanuele
31 jul 2013 18:29:01

@reikyoushin: usando un '1' devuelve todas las propiedades rentadas, y un '0' no devuelve ninguna propiedad.

Kegan Quimby Kegan Quimby
31 jul 2013 18:29:45

@iEmanuele: cambiar eso parece no tener efecto (pensé lo mismo). Lo vi en este artículo: http://thethemefoundry.com/blog/query-posts-wordpress-false-null-meta-value/

Kegan Quimby Kegan Quimby
31 jul 2013 18:30:44

Me refiero a usar 1 y 0 para los valores en lugar de booleanos, así no necesitas el meta_query... solo necesitas ordenarlos por 'meta_key' => '_price_rented', 'orderby' => 'meta_value', 'order' => 'ASC',

reikyoushin reikyoushin
31 jul 2013 18:37:10

¿Está _price_rented realmente establecido para ambos valores true y false, o solo está establecido para true? Revisa la base de datos por favor. Lo pregunto porque una casilla de verificación no marcada no se pasa a través de POST en absoluto, así que me pregunto si el valor está establecido para esos casos.

s_ha_dum s_ha_dum
31 jul 2013 18:45:55

Elimina 'meta_key' => '_price_rented' del array base. Podría ser que WP_Meta_Query se confunda al tener ambos. Por cierto, BOOLEAN no es válido y por lo tanto se restablecerá a CHAR, que es el valor predeterminado. Y si usas NUMERIC, intenta cambiarlo a SIGNED. También asegúrate de hacer un var_dump( get_post_meta( get_the_ID(), '_price_rented', true ) ); y añade esa salida a tu pregunta. Y si es "true" o "false", entonces establece value dentro de ese array como una cadena (rodeada de comillas).

kaiser kaiser
31 jul 2013 19:06:52

@s_ha_dum solo se establece como "true" si está marcado; si no está marcado, devuelve una cadena de caracteres 0.

Kegan Quimby Kegan Quimby
31 jul 2013 19:38:08

@kaiser 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 Kegan Quimby
31 jul 2013 19:40:04

Ver la solución en la respuesta.

kaiser kaiser
31 jul 2013 19:57:51

@KeganQuimby ¿algún progreso en ese?

kaiser kaiser
19 ago 2013 20:35:15
Mostrar los 6 comentarios restantes
Todas las respuestas a la pregunta 4
0
12

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

Más detalles:

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

Parte 1: Analicé el SQL generado por WP_Meta_Query para comparaciones con verdadero y falso, y descubrí que para verdadero sustituye '1' y para falso '' (la cadena vacía). Entonces, cualquier cosa que escribas en la base de datos debe coincidir con eso si vas a realizar consultas comparando con valores verdaderos y falsos. En particular, no querrás escribir '0' para falso. Podría ser más seguro escribir y probar con 0 y 1 (y muchos constructores de formularios hacen eso). Pero verifica qué se está escribiendo en la base de datos y tenlo en cuenta al construir tu consulta.

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

... 'meta_key' => 'mi_clave', 'meta_value' => 1 (o true)

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 listó como opcional en un formulario; mientras el usuario no lo establezca o cambie explícitamente, no se agregará a la base de datos. Ten en cuenta que si solo usas get_post_meta, funcionará bien de esta manera: devolver un valor falso y no devolver ningún valor logrará lo mismo.

Pero cuando usas WP_Query, no es tan fácil. (O si lo es, aún no he descubierto cómo).

Tienes dos (o quizás tres) opciones:

  1. Asegúrate de que el campo siempre se inicialice explícitamente con un valor real. En algunos constructores de formularios, haces esto haciendo que el campo sea obligatorio y dándole un valor predeterminado. Entonces puedes probar ...'meta_value' => 0 de manera confiable.

  2. Haz dos consultas, la primera que pruebe un valor falso y la segunda que pruebe la ausencia de valor. Estas se pueden combinar en una sola WP_Query así:

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

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

  1. Es posible usar 'sin valor' para significar falso. Para hacer esto, cada vez que el valor deba establecerse como falso, debes eliminar el valor meta en lugar de actualizarlo.

En ese caso, una sola consulta 'NOT EXISTS' devolverá de manera confiable los objetos correctos. (No creo que muchos constructores de formularios o plugins admitan este comportamiento, así que solo lo usaría en código completamente personalizado).

13 nov 2016 08:34:00
0

WP_Meta_Query es una parte del núcleo que de alguna manera "no es tan estable" y, si no prestas mucha atención, puede romperse fácilmente al confundirse.

Cuando realizas un new WP_Query() y tienes argumentos meta_query => array() o sus equivalentes de pares clave/valor únicos, entonces new WP_Meta_Query() entra en acción, seguido instantáneamente por el análisis.

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

Valores permitidos

Cuando consultas metadatos, existe la opción bool. Si la usaras, se revertiría a CHAR, que es el valor predeterminado, ya que la lista de valores permitidos es:

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

donde NUMERIC se restablecerá a SIGNED.

Depuración

Existen numerosos filtros que pueden afectar el proceso de guardado de publicaciones, por lo que lo primero que debes 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 devuelto, tendrás que usar SIGNED si el resultado es 0 o 1, o "true" o "false" si el resultado es una cadena. Si realmente es booleano, aún sugeriría usar string solo para asegurarte de que pase por $GLOBALS['wpdb'], que solo puede pasar cadenas %s y dígitos %d.

Notas adicionales

Como acabo de actualizar la entrada del Codex para WP_Meta_Query hoy, vi que hay muchas salidas diferentes (agregando cantidades numerosas de JOINS innecesarios, que se discuten en Trac aquí y aquí consin un solo parche incluido en el núcleo) posibles. (Ticket de seguimiento para partes AND aquí) El punto es que es posible usar una combinación de argumentos meta_* junto con el arreglo meta_query y sus subarreglos. El resultado es bastante desconocido a menos que lo vuelques, por lo que en mi opinión es mejor usar una forma o la otra de agregar entradas. Especialmente cuando solo usas meta_key, ya que esto resulta en una "consulta solo de clave" en algunos casos.

Solución

Como se señaló en los comentarios:

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

Ahora el meta_query debe usar

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

Si deseas obtener los "apartamentos no disponibles, alquilados" o usar '!=' para recuperar los apartamentos "no alquilados".

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

31 jul 2013 19:28:18
0

Me enfrenté al mismo problema y después de una hora de búsqueda encontré los valores "NOT EXISTS" y "EXISTS" (solo en WP >= 3.5). Así que no es necesario pedir un meta valor, solo verifica si el meta_key existe:

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

Funciona perfectamente para mí.

11 dic 2013 12:58:12
0

return false se registra como 0, return true se registra como 1

Por lo tanto, simplemente agrega value="1" a tu input type checkbox, para que pueda enviar el valor "1" si está marcado y no "on" por defecto

En tu meta query, hazlo como de costumbre:

array(
  'key'     => 'your_key',
  'value'   => 'your_value',
  'compare' => '='
)
11 dic 2024 19:21:38