【问题标题】:Laravel 5 Query builder LOGICAL NOTLaravel 5 查询生成器逻辑非
【发布时间】:2017-12-29 07:27:53
【问题描述】:

我需要将此 MYSQL 查询移植到 Laravel 5.2 查询构建器,但我不知道如何成功实现 Logical 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

我正在尝试使用 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();

【问题讨论】:

  • 如果您的查询对于查询构建器来说过于复杂,您始终可以使用hydrateRaw()Room::hydrateRaw($rawQuery, $bindings)
  • 我现在收到 SQLSTATE[HY093]: Invalid parameter number 错误,这里粘贴我的代码外观:pastebin.com/mQsjMVqV

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


【解决方案1】:

第一:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 2015-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-29
    • 2014-02-21
    相关资源
    最近更新 更多