Laravel 5.1获得已完成的订单

时间:2017-04-10 15:41:32

标签: php mysql eloquent laravel-5.1 pivot-table

我有一个Order模型和一个OrderStatus模型。 Order可以有多种状态,但只有一个“当前状态”。 (这由数据透视表created_at上的order_status时间戳定义。

Order模型(orders表)

OrderStatus模型(order_statuses表)

order_status数据透视表(order_status表)

如何定义查询范围(或类似)以获取某个状态的所有Orders;即完成'?

以下内容不起作用,因为它检查订单的所有状态,即使是过去的状态。

public function scopeCompleted($query)
{
    return $query->whereHas('statuses', function($q) {
        return $q->where('statuses.id', 10);
    });
}

生成的SQL是:

select  *
    from  `orders`
    where  `orders`.`deleted_at` is null
      and (
        SELECT  count(*)
            from  `statuses`
            inner join  `order_status`  ON `statuses`.`id` = `order_status`.`status_id`
            where  `status`.`id` = `orders`.`id`
              and  `statuses`.`id` = ?
          ) >= 1 

这错误地返回拥有的所有订单的ID为10的状态,而不是仅返回当前的状态ID为10的订单。 / p>

order_status 数据透视表

+----+----------+-----------------+-------------+---------------------+
| id | order_id | order_status_id | approver_id | approved_at         |
+----+----------+-----------------+-------------+---------------------+
| 11 | 2        | 9               | NULL        | 2017-04-10 13:33:25 |
+----+----------+-----------------+-------------+---------------------+
| 10 | 2        | 10              | NULL        | 2017-04-10 13:33:25 |
+----+----------+-----------------+-------------+---------------------+
| 9  | 2        | 5               | NULL        | 2017-04-10 13:33:25 |
+----+----------+-----------------+-------------+---------------------+
| 8  | 2        | 2               | NULL        | 2017-04-10 13:33:25 |
+----+----------+-----------------+-------------+---------------------+
| 7  | 2        | 1               | NULL        | 2017-04-10 13:33:25 |
+----+----------+-----------------+-------------+---------------------+
| 6  | 1        | 10              | NULL        | 2017-04-10 13:32:09 |
+----+----------+-----------------+-------------+---------------------+
| 5  | 1        | 9               | NULL        | 2017-04-10 13:32:05 |
+----+----------+-----------------+-------------+---------------------+
| 4  | 1        | 7               | NULL        | 2017-04-10 13:32:05 |
+----+----------+-----------------+-------------+---------------------+
| 3  | 1        | 5               | NULL        | 2017-04-10 13:32:05 |
+----+----------+-----------------+-------------+---------------------+
| 2  | 1        | 2               | NULL        | 2017-04-10 13:32:05 |
+----+----------+-----------------+-------------+---------------------+
| 1  | 1        | 1               | NULL        | 2017-04-10 13:32:05 |
+----+----------+-----------------+-------------+---------------------+

例如,上面的order_status数据透视表显示了两个包含多个状态条目的订单。由此,当要求完成的订单(状态10)时,只有一个订单(ID为1的订单)应该返回,因为订单2不再完成,它已经用另一个状态更新。

1 个答案:

答案 0 :(得分:0)

首先,这会更好:

select  *
    from  `orders`
    where  `orders`.`deleted_at` is null
      and EXISTS (
        SELECT  *
            from  `statuses`
            inner join  `order_status`
                ON `statuses`.`id` = `order_status`.`status_id`
            where  `status`.`id` = `orders`.`id`
              and  `statuses`.`id` = ?
                 );

你真的不需要全部计数,你只需要知道是否存在。

但是查询是不可能的,因为没有提到status表!

修复后,我们可以讨论如何避免子查询。