Laravel 5查询构建器LOGICAL NOT

时间:2017-07-23 17:57:37

标签: php laravel laravel-5.2 laravel-query-builder

我需要将此 MYSQL 查询移植到 Laravel 5.2查询生成器,我不知道如何成功实施逻辑NOT 部分:

SET @in='2017-06-01', @out='2017-06-01';

SELECT
  rooms.id,
  rooms.name,
  reservations.check_in,
  reservations.check_out,
  reservations.room_id
FROM
  rooms
  LEFT JOIN
  reservations
    ON rooms.id = reservations.room_id AND
    NOT (
        (reservations.check_in < @in AND reservations.check_out < @in)
        OR
        (reservations.check_in > @out AND reservations.check_out > @out)
    )
WHERE reservations.room_id IS NULL

我正在尝试使用查询构建器的原始查询,但它不起作用,我得到调用未定义的方法Illuminate \ Database \ Query \ Expression :: whereNull()错误

$free_rooms = Room
    ::select('rooms.id', 'rooms.name')
    ->leftJoin('reservations', 'rooms.id', '=', 'reservations.room_id') AND
            DB::raw("

            NOT (
                (reservations.check_in < $request->check_in AND reservations.check_out < $request->check_in) 
                OR 
                (reservations.check_in > $request->check_out AND reservations.check_out > $request->check_out)
            )

            ")
    ->whereNull('reservations.room_id')
    ->get();

1 个答案:

答案 0 :(得分:2)

首先:

    ->leftJoin('reservations', 'rooms.id', '=', 'reservations.room_id') AND

AND解析为PHP运算符 - 而不是SQL!

->whereNull('reservations.room_id')

链接在DB::raw(...)的结果上并导致异常。

第二:您的加入条件可以简化为

ON  rooms.id = reservations.room_id
AND reservations.check_out >= @in
AND reservations.check_in  <= @out

第三:如果查询的很大一部分是“原始”,最好不要使用查询构建器。用户hydrateRaw()改为

$rawQuery = "
    SELECT
      rooms.id,
      rooms.name
    FROM
      rooms
      LEFT JOIN
      reservations
        ON  rooms.id = reservations.room_id
        AND reservations.check_out >= :check_in
        AND reservations.check_in  <= :check_out
    WHERE reservations.room_id IS NULL
";

$bindings = [
    'check_in'  => $request->check_in,
    'check_out' => $request->check_out
];

$free_rooms = Room::hydrateRaw($rawQuery, $bindings);

请注意,我刚刚简化了保持逻辑的条件。但通常客户可以在另一个结账时(早上)在同一天(下午)办理登机手续。所以条件应该是

        AND reservations.check_out > :check_in
        AND reservations.check_in  < :check_out