【问题标题】:Multiple Where In多个在哪里
【发布时间】:2026-01-20 08:35:01
【问题描述】:

我正在使用 eloqent 过滤一组产品:

Product::whereIn('color', $color)->whereIn('size', $size)->whereIn('price', $price)->get();

上面的每一个变量都是一个id数组

$color = [1,2,4,5] 

我的问题是,当用户未能通过一组变量发送时,这是否效率低下,说他们不想要任何滤色器,所以数组将是:

$color = [];

我已经尝试过 ->toSql,它会生成 sql 语句:

select * from `products` where `color` in (?, ?) and 0 = 1 and `price` in (?, ?, ?, ?, ?)

在上面没有发送大小过滤器。

0 = 1 是什么意思?这是一种低效的处理方式吗?

【问题讨论】:

    标签: mysql laravel laravel-4 eloquent laravel-5


    【解决方案1】:

    这是一个非常有趣的问题。

    0 = 1 将始终为 false,因此您的查询将返回零行。但这是为什么呢?

    因为设置

    ->whereIn('size', $size)
    

    Laravel 假定您总是希望返回的行具有传递数组中的大小之一。如果你没有在数组中传递任何值,Laravel 不能这样做where size IN (),因为这将是语法错误(你基本上说给我所有匹配这个大小的行,但你不传递大小)。所以如果数组是空的,它只会放0 = 1

    为了告诉 Laravel,如果没有传递 size,不添加 size 条件,只需在此之前进行一个简单的检查。

    $product = new Product;
    
    if (!empty($sizes)) {
        $product = $product->whereIn('size', $sizes);
    }
    
    $products = $product->get();
    

    顺便说一句,这种行为是hotfix。在以前的 Laravel 版本中,如果您传递空数组,您只会因语法错误而引发异常。现在只需设置1 = 0即可处理

    【讨论】:

    • 谢谢。所以我应该做类似 $query = Product::all();然后对每个过滤器进行 where 检查,如果不为空,请执行 $query->whereIn('myfilter', $requestedFilter);这会不会做不止一个查询并且效率低下?
    • @panthro no,Product::all() 将立即获取所有产品。您应该这样做:$product = new Product; 然后进行检查并添加条件。
    • 那么它会不会像 $product = new Product; //检查过滤器; $product->get();
    • @panthro 没错。我已经用一个例子编辑了我的答案。
    • @panthro 是的。在您调用 ->get() 之前不会执行任何查询