Где предложение, когда переменная false, не учитывает это в SQL-запросе?

У меня есть кое-что, что я не совсем понимаю, у меня есть решение, но я не знаю, почему и это заставляет меня немного сходить с ума

контроллер

DB::connection()->enableQueryLog();

$transfer = Transfer::where('ticket_id', $last_ticket)->where('event_id', 36)->where('buyer', $user_email)->first();

$queries = DB::getQueryLog();

dd($queries);

Результат

array:1 [
  0 => array:3 [
    "query" => "select * from 'transfers' where 'ticket_id' = ? and 'event_id' = ? and 'buyer' = ? limit 1"
    "bindings" => array:3 [
      0 => false
      1 => 36
      2 => "[email protected]"
    ]
    "time" => 0.36
  ]
]

Ситуация: $last_ticket в БД уникален и никогда не является null, пустым или false.

В моем примере $last_ticket является false, но в БД нет никакого false, почему я все еще получаю результаты?

Это потому, что всякий раз, когда условие ложно, оно не принимает этого в уравнение?

Таким образом, возникает вопрос: как я могу сделать, чтобы получить правильные значения результатов: если $ last_ticket является ложным, то никаких результатов, и если у него есть некоторые данные, тогда возвращаем результат строки, ограниченный $ last_ticket

Один вариант может состоять в том, чтобы поставить if($last_ticket == false){$last_ticket='randomInexistentString_ag4dh&2g32y4t'} чтобы он не был нулевым или нулевым, но я не думаю, что это более красивый способ пойти

Ответ 1

Нуль в MySQL всегда соответствует любой строке, которая не начинается с цифры - это потому, что она хочет, чтобы обе стороны сравнения были одного типа, поэтому она преобразует строку в число, а любая строка, которая не начинать с цифры автоматически оценивается 0.

Теперь вы не кормите его 0 но вы кормите его false, а в MySQL - не истинным логическим, а фактически 0.

Не зная точно, как выглядит ваша база данных, я бы сказал, что это наиболее вероятное объяснение.

Есть способы обойти это, например, вы можете использовать цепочку ->when() в Eloquent:

Transfer::where('event_id', 36)
        ->where('buyer', $user_email)
        ->when($last_ticket, function ($query) use ($last_ticket) {
            $query->where('ticket_id', $last_ticket);
        })
        ->first();

(Взятый из памяти, синтаксис может немного отделиться. Спасибо Рику Джеймсу за исправление комментариев).

Ответ 2

Редизайн интерфейса. Если что-то нужно оставить вне запроса, не включайте его в запрос.

То есть, динамически создайте WHERE, чтобы при поставке "false" оно становится

WHERE 'event_id' = ? and 'buyer' = ?

Я не знаю о Laravel, но в PHP я бы создал массив вещей для AND и затем WHERE:

$ands = array();
if (...)  $ands[] = "ticket_id = ...";
if (...)  $ands[] = "event_id = ...";
if (...)  $ands[] = "buyer = ...";

if (empty($ands))
    $where = '';
else
    $where = 'WHERE ' . implode(' AND ', $ands);

$sql = "SELECT ... $where ...";

Обратите внимание, что он легко обрабатывает любой или все или ни один из элементов, которые опущены.