【问题标题】:Laravel eloquent where and orWhere issue fetching correct dataLaravel 雄辩的 where 和 orWhere 问题获​​取正确的数据
【发布时间】:2018-04-21 14:28:48
【问题描述】:

我有以下生成此查询的查询生成器:

当使用最低和最高价格过滤时,我的问题在于销售和股票期权的 where 条件。我的网址如下所示:

category/men-clothes?sale=no_sale&min_price=10&max_price=10000&per_page=8

sale=no_sale,表示查询执行 where 'sale_price', '=', 0,因此在我的 SQL 查询中:

and `sale_price` = ? order by `id` desc

然而,它仍然会获取 sale_price 大于 0 的产品,但是当我切换到 on_sale 时,只会获取 sale_price 大于 0 的产品。所以问题只是在选择没有活跃销售的产品时。 on_stock 和 no_stock 也是如此,它只是没有获取正确的产品。我知道建设者很大,但我无法弄清楚为什么它不能正常工作。它只有在我完全删除 min_price 和 max_price 过滤后才能正常工作,因此它必须位于导致这些问题的价格过滤中 where 和 orWhere 的某个位置。

.

select * from `products` where exists (select * from `categories` inner join `product_categories` on `categories`.`id` = `product_categories`.`category_id` where `products`.`id` = `product_categories`.`product_id` and `id` = ?) and (`has_variants` = ? and `price` >= ?) or (`has_variants` = ? and `min_price` != ? and `min_price` >= ?) and (`has_variants` = ? and `price` <= ?) or (`has_variants` = ? and `max_price` != ? and `max_price` <= ?) and `sale_price` = ? order by `id` desc  

.

$products = Product::whereHas('categories', function ($query) use ($category) {
            $query->where('id', '=', $category->id);
        })->when(count($brand_list) > 0, function ($query) use ($brand_list) {
            $query->whereHas('brand', function ($query) use ($brand_list) {
                $query->whereIn('slug', $brand_list);
            });
        })->when($minPrice, function ($query) use ($data) {
            $query->where([
                    ['has_variants', '=', 0],
                    ['price', '>=', $data['active_filters']['min_price']],
                ])
                ->orWhere([
                    ['has_variants', '=', 1],
                    ['min_price', '!=', 0],
                    ['min_price', '>=', $data['active_filters']['min_price']],
                ]);
        })->when($maxPrice, function ($query) use ($data) {
            $query->where([
                ['has_variants', '=', 0],
                ['price', '<=', $data['active_filters']['max_price']],
            ])
                ->orWhere([
                    ['has_variants', '=', 1],
                    ['max_price', '!=', 0],
                    ['max_price', '<=', $data['active_filters']['max_price']],
                ]);
        })->when($orderPrice, function ($query) use ($orderPrice) {
            $query->orderBy('price', $orderPrice);
        })->when(!$orderPrice, function ($query) {
            $query->orderBy('id', 'desc');
        })->when($stockOrder, function ($query) use ($stockOrder) {
            if($stockOrder == 'in_stock') {
                $query->where('quantity', '>', 0);
            } else if($stockOrder == 'no_stock') {
                $query->where('quantity', '=', 0);
            }
        })->when($saleOrder, function ($query) use ($saleOrder) {
            if($saleOrder == 'on_sale') {
                $now = time();
                $query->where([
                    ['sale_price', '>', 0],
                    ['sale_start', '<', $now],
                    ['sale_end', '>', $now],
                ])->orWhere([
                    ['sale_price', '>', 0],
                    ['sale_start', '=', 0],
                    ['sale_end', '=', 0],
                ]);
            } else if($saleOrder == 'no_sale') {
                $query->where('sale_price', '=', 0);
            }
        })->when($featuredOrder, function ($query) use ($featuredOrder) {
            if($featuredOrder == 'featured') {
                $query->where('featured', '=', 1);
            } else if($featuredOrder == 'not_featured') {
                $query->where('featured', '=', 0);
            }
        })->when(count($activeColors) > 0, function ($query) use ($activeColors) {
            $query->whereHas('colors', function ($query) use ($activeColors) {
                $query->whereIn('value', $activeColors);
            });
        })->when(count($activeSizes) > 0, function ($query) use ($activeSizes) {
            $query->whereHas('sizes', function ($query) use ($activeSizes) {
                $query->whereIn('value', $activeSizes);
            });
        })->with(['colors', 'sizes', 'reviewsCount'])->get();

【问题讨论】:

    标签: php laravel laravel-5 eloquent laravel-eloquent


    【解决方案1】:

    我认为这里的问题是orWhere。当您使用 orWhere 时,您可能应该始终使用额外的闭包来包装构造。我们来看看:

    ->when($minPrice, function ($query) use ($data) {
                $query->where([
                        ['has_variants', '=', 0],
                        ['price', '>=', $data['active_filters']['min_price']],
                    ])
                    ->orWhere([
                        ['has_variants', '=', 1],
                        ['min_price', '!=', 0],
                        ['min_price', '>=', $data['active_filters']['min_price']],
                    ]);
            })
    

    这部分应该是这样的:

    ->when($minPrice, function ($query) use ($data) {
          $query->where(function($query) use ($data) {
                $query->where([
                        ['has_variants', '=', 0],
                        ['price', '>=', $data['active_filters']['min_price']],
                    ])
                    ->orWhere([
                        ['has_variants', '=', 1],
                        ['min_price', '!=', 0],
                        ['min_price', '>=', $data['active_filters']['min_price']],
                    ]);
              });
            })
    

    正如您在上面看到的,整个 where .. orWhere 被包裹在额外的闭包中。

    原因很明显。如果您没有额外的闭包,您可以生成这样的查询

    WHERE A and B or C and D or E
    

    通常应该是这样的:

    WHERE A and (B or C) and (D or E)
    

    因此,当您使用闭包时,它们会在查询中添加额外的括号以使其正常工作。

    显然,您应该以同样的方式包装所有其他 where ... orWhere 结构,以使其按预期工作

    【讨论】:

    • 好的,谢谢。我只需要用额外的 where 将所有 where 子句包裹起来。太感谢了!它现在就像一个魅力。
    猜你喜欢
    • 2023-04-05
    • 1970-01-01
    • 2014-11-09
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 2017-11-05
    • 2021-02-13
    • 1970-01-01
    相关资源
    最近更新 更多