Laravel 关系 whereRaw 约束内部 with() 方法

Posted

技术标签:

【中文标题】Laravel 关系 whereRaw 约束内部 with() 方法【英文标题】:Laravel relationship whereRaw constraint inside with() method 【发布时间】:2019-01-07 07:18:03 【问题描述】:

我有两个表,“Employee”和“EmployeeLeaveLog”。 我正在尝试使用下面的代码让员工记录他们当月的休假记录,但它向我显示了一个错误。

我想放在 whereRaw() 中的 sql 代码是:

SELECT * FROM employee_leave_log
WHERE UNIX_TIMESTAMP(from_date) >= UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + 
INTERVAL 1 DAY - INTERVAL 1 MONTH)
AND ( (till_date IS NULL) OR (UNIX_TIMESTAMP(till_date) <  
UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY)));

而 Laravel 代码是:

Employee::with(['leaveRecord' => function($query) 
$query->whereRaw("((UNIX_TIMESTAMP(from_date) >= 
(UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY - INTERVAL 1 MONTH))) 
AND ( (till_date IS NULL) OR (UNIX_TIMESTAMP(till_date) <  
UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY))))");
 ])->all();

编辑:

EmployeeLeaveTable 有以下主要列:

leave_log_id,

employee_id,

从_日期,

till_date(如果只申请一天请假,则为 Null。)

编辑 2: 我在 whereRaw() 中的 SQL 代码中发现了一个逻辑错误。

正确的 SQL 代码应该是:

SELECT * FROM employee_leave_log
    WHERE (
              (
                  (UNIX_TIMESTAMP(from_date) >= UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY - INTERVAL 1 MONTH))
                  AND
                  (UNIX_TIMESTAMP(from_date) < UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY))
              )
              OR
              (
                  (UNIX_TIMESTAMP(till_date) >= UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY - INTERVAL 1 MONTH))
                  AND
                  (UNIX_TIMESTAMP(till_date) < UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY))
              )
          );

【问题讨论】:

你是什么意思当月离开记录? @Leorent 离开了当月已经拍摄的。 【参考方案1】:

回答我自己的问题。终于找到问题了,SQL语句出现逻辑错误。

以下代码应该可以工作:-

Employee::with(['leaveRecord' => function ($query) 
$query->whereRaw("(
                  (UNIX_TIMESTAMP(from_date) >= UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY - INTERVAL 1 MONTH))
                  AND
                  (UNIX_TIMESTAMP(from_date) < UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY))
              )
              OR
              (
                  (UNIX_TIMESTAMP(till_date) >= UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY - INTERVAL 1 MONTH))
                  AND
                  (UNIX_TIMESTAMP(till_date) < UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY))
              )"))->get();

【讨论】:

【参考方案2】:

要获得当前月份的假期,您可以执行以下操作:

Employee::with(['leaveRecord' => function ($query) 
    $query->whereDate('from_date', '>=', Carbon::now()->startOfMonth());
    $query->whereDate('till_date', '<=', Carbon::now()->endOfMonth());
])->get();

【讨论】:

没用。如果只有一天的假期,till_date 列可以为空。【参考方案3】:

你遇到了什么错误?

你可以试试这个:

Employee::with(['leaveRecord' => function ($query) 
    $query->whereDate('from_date', '>=', Carbon::now()->startOfMonth())
       ->whereNull('till_date')
       ->orWhereDate('till_date', '<=', Carbon::now()->endOfMonth());
])->get();

更新,试试这个:

Employee::with(['leaveRecord' => function ($query) 
    $query->whereDate('from_date', '>=', Carbon::now()->startOfMonth())
        ->where(function ($query) 
            return $query->whereNull('till_date')
                ->orWhereDate('till_date', '<=', Carbon::now()->endOfMonth());
        );
])->get();

这应该将第二部分包含在 () 中以解决问题。

【讨论】:

不工作...查询生成的SQl错误。 这里是生成的 SQL - "select * from employee_leave_log where date(from_date) >= ? and till_date is null or date(till_date) @Tintin 我已经更新了我的答案,你可以试试看它是否按预期工作? 它省略了一条记录,其中 from_date 是 '2018-12-30 00:00:00' 而 till_date 是 '2019-01-02 00:00:00',你知道为什么吗? 好的,我在问题中发布的 SQL 查询中发现了一个逻辑错误...让我修复它。

以上是关于Laravel 关系 whereRaw 约束内部 with() 方法的主要内容,如果未能解决你的问题,请参考以下文章

Laravel QueryBuilder - 相同查询的 `where()` 和 `whereRaw()` 结果不同

Laravel Eloquent 嵌套关系枢轴与约束

Laravel 关系和外键约束

在 laravel 中定义 eloquent 关系时添加额外的约束

Laravel 约束急切加载 - 如果关系列应用限制!= 1

在 laravel 5.2 中使用工厂关系违反完整性约束