Laravel 5 查询生成器逻辑非

Laravel 5 Query builder LOGICAL NOT

我需要将此 MYSQL 查询移植到 Laravel 5.2 Query Builder 但我不知道了解如何成功实施 逻辑非 部分:

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

我正在尝试使用 Query Builder 的原始查询,但它不起作用,我得到一个 对未定义方法的调用 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();

第一个:

    ->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

第三: 如果查询的很大一部分是 "raw",最好根本不要使用查询生成器。用户 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