Мета-запрос с логическим значением true / false

11

Я пытаюсь показать все свойства, сдаваемые в аренду, сначала по всем объектам, которые не были сданы в аренду, а затем по всем объектам, которые в настоящее время сданы в аренду. Существует специальный тип поста 'rent' с пользовательским мета-значением поста для арендованной цены (_price_rented), который является флажком (возвращает либо true, либо false ... true, если он был арендован). Мне нужно изменить запрос, чтобы показать все свойства, в которых сначала отображаются доступные (не арендованные) свойства, а затем - арендованные свойства.

Вот мой запрос:

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

По какой-то причине этот запрос показывает все свойства, которые были арендованы. Когда я переключаю значение с «false» на «true» в meta_query, оно не показывает никаких свойств.

Итак, потом я подумал, что возвращаемое значение - либо false (для свойств, которые АРЕНДОВАНЫ), либо NULL (для свойств, НЕ АРЕНДОВАННЫХ), но я не уверен, как запросить результат NULL (не false), я добавил ' сравните аргумент с мета-запросом и установите значение '! =', но это тоже не сработало.

РЕДАКТИРОВАТЬ: var_dump возвращает следующее для доступной, не арендованной квартиры: string(0) ""и для недоступной, арендованной квартиры:string(1) "1"

Кеган Квимби
источник
используя значения 1 и 0 возможно?
Рейкюшин
meta_query type => string. Возможные значения: «NUMERIC», «BINARY», «CHAR», «DATE», «DATETIME», «DECIMAL», «SIGNED», «TIME», «UNSIGNED». Значением по умолчанию является «CHAR».
iEmanuele
@reikyoushin: использование «1» возвращает все арендованные свойства, а «0» - никаких свойств.
Кеган Квимби,
1
@iEmanuele: изменение, которое, кажется, не имеет никакого эффекта (я думал то же самое). Я видел это из этой статьи: thethemefoundry.com/blog/…eg
Кеган Квимби
1
Является ли на _price_rentedсамом деле установить для обоих trueи falseзначений, или она устанавливается только для true? Проверьте базу данных, пожалуйста. Я спросил, потому что непроверенный флажок вообще не пропущен, POSTпоэтому мне интересно, установлено ли значение вообще для этих случаев.
s_ha_dum

Ответы:

4

WP_Meta_Query это как-то «не очень стабильная» часть в ядре, и если вы не уделяете много внимания, она может легко сломаться от путаницы.

Когда вы выполняете a new WP_Query()и имеете meta_query => array()аргументы или их единственную пару ключ / значение, затем new WP_Meta_Query()включается сразу же после анализа.

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

Допустимые значения

Когда вы запрашиваете метаданные, тогда есть boolопция. И если бы вы использовали его, то он вернулся бы к тому CHAR, что значение по умолчанию в качестве массива допустимых значений:

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

где NUMERICбудет сброшен SIGNED.

Отладка

Существует множество фильтров, которые могут повлиять на процесс сохранения после записи, поэтому первое, что нужно сделать, это проверить различные значения внутри некоторого цикла:

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

Затем, в зависимости от возвращаемого значения, вам придется либо использовать SIGNED, если результатом является 0либо 1, либо, "true"или "false"если результатом является строка. Если это действительно логическое значение, то я бы по-прежнему предлагал использовать его, stringчтобы убедиться, что он проходит $GLOBALS['wpdb'], который может передавать только %sстроки и %dцифры.

Дополнительные замечания

Как я только что обновил запись Кодекса наWP_Meta_Query сегодняшний день, я увидел , что там уже много различных выходов (добавление многочисленного количества ненужного JOINS, которые обсуждаются на Trac здесь и здесь с из одного патча перемещается в ядро) возможно. (Последующий билет на ANDчасть здесь ) Точка является то , что это можно использовать комбинацию meta_*аргументов наряду с meta_queryмассивом и его подрешеток. Результат в значительной степени неизвестен, если вы не сбросите его, так что IMHO вам лучше использовать тот или иной способ добавления входных данных. Особенно когда ты толькоиспользуя meta_key, так как это приводит к «запросу только ключа» в некоторых случаях.

Решение

Как указано в комментариях:

(...) var_dumpвозвращает следующее для доступной, не арендованной квартиры: string(0) ""и для недоступной, арендованной квартиры:string(1) "1"

Теперь meta_queryнужно использовать

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

Если вы хотите получить «недоступные, арендованные квартиры» или использовать '!='для получения «не арендованных» квартир.

Примечание. Возможные значения meta_compare: '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'NOT EXISTS', 'REGEXP', 'NOT REGEXP'or или 'RLIKE'. По умолчанию значения '='.

кайзер
источник
3

Я столкнулся с той же проблемой , и после часа поисков нашел "NOT EXISTS"и "EXISTS"значение ( only in WP >= 3.5 ). Поэтому нет необходимости запрашивать мета-значение, просто проверьте, существует ли meta_key:

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

Это прекрасно работает для меня.

Тибо
источник
3

TL; DR: эта проблема, вероятно, чаще всего возникает, когда логическое поле создается как необязательное. Вы можете исправить это, либо сделав это обязательным, либо используя более сложный запрос для получения случая по умолчанию.

Больше деталей:

Здесь возникают две проблемы с представлением данных: первая - какие значения данных используются для представления значений true / false, а другая - хранится ли поле вообще, если это значение по умолчанию (обычно false).

Часть 1: Я посмотрел на SQL, сгенерированный с помощью WP_Meta_Queryсравнений с true и false, и обнаружил, что для true он заменяет '1' и для false '' (пустая строка). Поэтому все, что вы записываете в базу данных, должно соглашаться с этим, если вы собираетесь делать запросы, сравниваемые с фактическими значениями true и false. В частности, вы не хотите писать «0» для false. Это может быть более надежным, чтобы писать и тестировать для 0 и 1 вместо этого (и многие сборщики форм делают это). Но проверьте, что записывается в базу данных, и помните об этом при создании запроса.

Часть 2. Предполагая, что false является значением по умолчанию, найти записи, значение которых равно true, легко:

... 'meta_key' => 'my_key', 'meta_value' => 1 (или правда)

Но с другой стороны сложно: может быть ложное значение или вообще не может быть никакого значения. Это может произойти, если значение было указано как необязательное в форме - тогда, пока пользователь явно не установит его или не изменит его, оно не будет добавлено в базу данных. Обратите внимание, что если вы используете только get_post_metaэто, то все будет работать нормально: возвращение ложного значения и отсутствие значения приведет к тому же результату.

Но когда вы используете WP_Query, это не так просто. (Или, если это так, я еще не понял, как).

У вас есть два (или, может быть, три) варианта:

  1. Убедитесь, что поле всегда явно инициализируется реальным значением. В некоторых построителях форм вы делаете это, делая обязательное поле и присваивая ему значение по умолчанию. Тогда вы можете проверить ...'meta_value' => 0 надежно.

  2. Выполните два запроса: первый, который проверяет ложное значение, а второй, который проверяет отсутствие значения. Их можно объединить в один WP_Query следующим образом:

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

Это, вероятно, не эффективный запрос. В зависимости от множества факторов, может быть лучше вернуть все объекты и отфильтровать их в своем собственном коде.

  1. Можно использовать «нет значения», чтобы означать ложь. Чтобы сделать это, всякий раз, когда значение должно быть установлено в false, вы должны удалить мета-значение вместо его обновления .

В этом случае один 'NOT EXISTS'запрос надежно вернет правильные объекты. (Я не думаю, что многие конструкторы форм или плагины поддерживают это поведение, поэтому я бы использовал его только в собственном коде.)

Дениз Дрэйпер
источник