doutao1939 2017-04-10 10:09
浏览 55
已采纳

Laravel Query Builder:意外输出

For the last two hours I'm struggling with a MySQL query that is created using the Laravel Query Builder, but I just don't understand why a parameter seems to be ignored.

The query that comes out of the query builder is the following:

select * from `deals` where
(
    (   
        `created_at` <= '2017-04-10 09:44:07' 
        and `valid_until` >= '2017-04-10 09:44:07'
    ) or (
        `created_at` <= '2017-04-10 09:44:07' 
        and `valid_until` <= '2017-04-10 09:44:07' 
        and `autodelete` = '2'
    ) or (
        `created_at` <= '2017-04-10 09:44:07'
        and `valid_until` <= '2017-04-10 09:44:07' 
        and `autodelete` = '0'
    ) or (
        `created_at` <= '2017-04-10 09:44:07'
        and `valid_until` is null
    )
    and `category_id` != '1'
) and `deals`.`deleted_at` is null
order by `order_date` desc, `created_at` desc 
limit 20 
offset 0

The part that is being ignored is the filtering of the category_id. Items that have the category_id 1 should be excluded, but they won't. And I don't understand why.

Now I found out that when I move that part to outside the parentheses, it will work. The only problem is: I'm not adding those parentheses to the query, it seems that Laravel is doing that automatically because I'm using soft deletes.

This is the code I'm using for creating the query:

        $query = Deal::query()
        ->where(function ($query) {
            // Active with an end date
            $query->where('created_at', '<=', date("Y-m-d H:i:s"))
            ->where('valid_until', '>=', date("Y-m-d H:i:s"));
        })
        ->orwhere(function ($query) {
            // Ended, but with possibility to upload a receipt
            $query->where('created_at', '<=', date("Y-m-d H:i:s"))
            ->where('valid_until', '<=', date("Y-m-d H:i:s"))
            ->where('autodelete', 2);
        })
        ->orwhere(function ($query) {
            // Ended, but keep it online
            $query->where('created_at', '<=', date("Y-m-d H:i:s"))
            ->where('valid_until', '<=', date("Y-m-d H:i:s"))
            ->where('autodelete', 0);
        })
        ->orwhere(function ($query) {
            // No end date
            $query->where('created_at', '<=', date("Y-m-d H:i:s"))
            ->where('valid_until', null);
        });

// Filter categories
if(!empty($deselectedCategories))
{
    foreach($deselectedCategories as $key => $val)
    {
        $query->where('category_id', '!=', $val);
    }
}

$deals = $query->orderBy('order_date', 'desc')->orderBy('created_at', 'desc')->paginate($resultsPerPage);

I must be overlooking something and I hope someone can help me out. Thank you very much in advance!

  • 写回答

1条回答 默认 最新

  • douluogu8713 2017-04-10 11:50
    关注

    Kindly take a close look at your parameter grouping https://laravel.com/docs/5.4/queries#parameter-grouping

    I have restructured the query

    1. Removed the and category_id != {Val} to use whereNotIn
    2. Regrouped the query

      $query = Deal::where(function
               ($query){
                  $query->where(function ($query) {
                                          // Active with an end date
                      $query->where('created_at', '<=', date("Y-m-d H:i:s"))
                      ->where('valid_until', '>=', date("Y-m-d H:i:s"));
                  })
                  ->orwhere(function ($query) {
                      // Ended, but with possibility to upload a receipt
                      $query->where('created_at', '<=', date("Y-m-d H:i:s"))
                      ->where('valid_until', '<=', date("Y-m-d H:i:s"))
                      ->where('autodelete', 2);
                  })
                  ->orwhere(function ($query) {
                                          // Ended, but keep it online
                      $query->where('created_at', '<=', date("Y-m-d H:i:s"))
                      ->where('valid_until', '<=', date("Y-m-d H:i:s"))
                      ->where('autodelete', 0);
                  })
                  ->orwhere(function ($query) {
                                          // No end date
                      $query->where('created_at', '<=', date("Y-m-d H:i:s"))
                      ->where('valid_until', null);
                  });
              });
      
            if (!empty($deselectedCategories)) {
                $catList =array();
                foreach ($deselectedCategories as $key => $val) {
                    $catList[] = $val;
                }
             $query->whereNotIn('category_id', $catList);
          }
      $query->whereNull('deleted_at');
      $deals = $query->orderBy('order_date', 'desc')->orderBy('created_at', 'desc')->paginate($resultsPerPage);
      
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 微信会员卡等级和折扣规则
  • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
  • ¥70 2048小游戏毕设项目
  • ¥20 mysql架构,按照姓名分表
  • ¥15 MATLAB实现区间[a,b]上的Gauss-Legendre积分