Laravel 5.1 - 以错误的顺序应用子查询参数绑定?

时间:2017-02-04 09:55:05

标签: php laravel-5.1 laravel-query-builder laravel-eloquent parameterbinding

我有以下更新查询,其中包含一个子查询连接(我不得不使用DB:Raw,因为我无法通过任何其他方法找到任何文档来完成 - 除非有人可以告诉我一些其他方法来实现它)。

但是,由于正在更新的表/模型使用时间戳,因此还会添加updated_at的值并混淆参数绑定的顺序?

OrderItemProduct::from('order_item_product as t1')
        ->join(DB::Raw('(
           SELECT t1.product_id as product_id
                , MIN(t1.created_at) as created_at
                , MIN(t1.order_item_id) as order_item_id
             FROM order_item_product t1
      INNER JOIN order_items t2 on t1.order_item_id = t2.id
      INNER JOIN orders t3 on t2.order_id = t3.id
           WHERE t1.product_id = ?
             AND t1.available > 0
             AND TIMESTAMPADD(DAY,t1.valid_days,t1.created_at) > now()
             AND t3.user_id = ?
        GROUP BY t1.product_id) AS t2'), function($join)
        {
                $join->on('t1.order_item_id', '=', 't2.order_item_id');
                $join->on('t1.created_at', '=', 't2.created_at');

         })
        ->setBindings([$productId, $userId])
        ->decrement('t1.available');

以下是我在转储查询日志时的最终结果:

array:1 [▼
   0 => array:3 [▼
     "query" => """
       update `order_item_product` as `t1` inner join (\r\n
                 SELECT t1.product_id as product_id\r\n
  \t                  , MIN(t1.created_at) as created_at\r\n
  \t\t                , MIN(t1.order_item_id) as order_item_id\r\n
  \t\t             FROM order_item_product t1\r\n
             INNER JOIN order_items t2 on t1.order_item_id = t2.id\r\n
             INNER JOIN orders t3 on t2.order_id = t3.id\r\n
                  WHERE t1.product_id = ?\r\n
                    AND t1.available > 0\r\n
                    AND TIMESTAMPADD(DAY,t1.valid_days,t1.created_at) > now()\r\n
  \t                AND t3.user_id = ?\r\n
               GROUP BY t1.product_id) AS t2 ON `t1`.`order_item_id` = `t2`.`order_item_id` 
                   AND `t1`.`created_at` = `t2`.`created_at` 
                   SET `t1`.`available` = `t1`.`available` - 1, `updated_at` = ?
       """
     "bindings" => array:3 [▼
         0 => "2017-02-04 09:41:22"
         1 => 1
         2 => 1
     ]
     "time" => 2.9
   ]
]

正如您在bindings数组中看到的那样,updated_at的值会在索引0处由eloquent自动添加,因此它最终被绑定到查询中的第一个参数占位符,这是不正确的。

因此,WHERE t1.product_id = 1代替WHERE t1.product_id = "2017-02-04 09:41:22"而不是所有其他参数 - 而且所有其他参数都是错误的。

为什么将updated_at列的值首先添加到绑定数组中 - 不应该将它添加到数组的末尾?

我该如何解决这个问题?

*更新*

当我检查Illuminate\Database\Eloquent\Builder方法的decrement时,我会看到以下内容:

public function decrement($column, $amount = 1, array $extra = [])
{
    $extra = $this->addUpdatedAtColumn($extra);

    return $this->query->decrement($column, $amount, $extra);
}

protected function addUpdatedAtColumn(array $values)
{
    if (! $this->model->usesTimestamps()) {
        return $values;
    }

    $column = $this->model->getUpdatedAtColumn();

    return Arr::add($values, $column, $this->model->freshTimestampString());
}

Arr :: add执行以下操作:

public static function add($array, $key, $value)
{
    if (is_null(static::get($array, $key))) {
        static::set($array, $key, $value);
    }

    return $array;
}

因此,为了排除它被addUpdatedAtColumn方法添加,我必须在更新查询中包含该列,如下所示:

`->decrement('t1.available', 1, ['updated_at' => DB::Raw('now()')]);`

0 个答案:

没有答案