2017-10-19 61 views
4

我正在研究一些产品的过滤器。我有大部分工作,但我遇到了一个不可能的where条款的错误。Laravel不可能在哪里查询

该表包含单个产品的多行,我试图匹配每个产品的多个标准,这导致它失败。

如果您对此有任何意见或者解决方法,我将不胜感激。

数据库表如下所示:

 
    -------------------------------------------- 
    |id | FilterKey | filterValue | product_id | 
    -------------------------------------------- 
    |1 | Colour | Gunmetal | 1   | 
    |2 | Colour | Silver  | 1   | 
    |3 | Size  | 750cc  | 1   | 
    |4 | Size  | 1000cc  | 1   | 
    |5 | Colour | Red   | 2   | 
    |6 | Colour | Blue  | 2   | 
    |7 | Size  | 750cc  | 2   | 
    |8 | Size  | 1000cc  | 2   | 
    -------------------------------------------- 

和过滤器看起来像这样:

public function scopeFilterProduct($query, $filters) 
{ 
    $this->filters = $filters; 
    if (count ($this->filters) === 1 && isset($this->filters[0])) 
    { 
     return $query; 
    } 
    $query->join('product_filters', 'products.id', '=', 'product_filters.product_id')->Where(function($query){ 
     foreach ($this->filters as $filter => $vals) 
     { 
      $this->filter = $filter; 
      $this->vals = $vals; 
      $query->Where(function ($query){ 

       $query->Where('filterKey', $this->filter); 

       $query->Where(function($query){ 
        foreach ($this->vals as $val){ 

         $query->orWhere('filterValue', $val); 
        } 
        $this->vals = null; 
       }); 

      }); 
      $this->filter = null; 
     }; 
    }); 
    return $query; 
} 

这则输出下面的SQL语句:

select 
    distinct 
    `products`.`id` 
    , `product_id` 
from 
`products` 
inner join 
`product_filters` 
on 
`products`.`id` = `product_filters`.`product_id` 
where 
    (
     (`filterKey` = 'Colour' and (`filterValue` = 'gunmetal')) 
     and 
     (`filterKey` = 'Size' and (`filterValue` = '750cc')) 
    ) 
    and 
     `products`.`deleted_at` is null 

如果选择了屏幕截图,那么只有'产品一'应该出现在页面上。

+0

这就是所谓的一组division.The逻辑遵循的是“得到的产物为其中不存在选择的过滤器,它没有“ – apokryfos

回答

0

您在我看来添加的范围是错误的。即使你的数据库结构在我看来是不正确的。这是我怎么会结构本:

过滤器表

这种模式将保存所有过滤器值。例如,ColourSize等。这里是怎样的过滤表的结构将:

----------------- 
|id | name  | 
----------------- 
|1 | Colour | 
|2 | Size  | 
----------------- 

所以,你的口才模型成为这样的事情:

class Filter extends Model 
{ 
    protected $fillable = ['id', 'name']; 

    public function products() 
    { 
     return $this->belongsToMany(Product::class, 'products_filters');   
    } 
} 

产品表

您的产品型号变为:

class Product extends Model 
{ 
    public function filters() 
    { 
     return $this->belongsToMany(Filter::class, 'products_filters');   
    } 
} 

products_filters表

上述变化后,这里是怎样的表将被结构化:

-------------------------------------------- 
|id | filter_id | filterValue | product_id | 
-------------------------------------------- 
|1 | 1   | Gunmetal | 1   | 
|2 | 1   | Silver  | 1   | 
|3 | 2   | 750cc  | 1   | 
|4 | 2   | 1000cc  | 1   | 
|5 | 1   | Red   | 2   | 
|6 | 1   | Blue  | 2   | 
|7 | 2   | 750cc  | 2   | 
|8 | 2   | 1000cc  | 2   | 
-------------------------------------------- 

现在,你可以简单地查询过滤器表,然后获取相关产品的所有过滤器。之后,你只需编译一个独特的产品列表。

根据所选过滤器提供同类产品。

$ids = []; 
$products = new \Illuminate\Support\Collection(); 

foreach($filters as $filter) { 
    foreach($filter->products as $product) { 
     if(!in_array($product->id, $ids)) { 
      $ids[] = $product->id; 
      $products->push($product); 
     } 
    } 
} 

return view('results', compact('products')); 

在你看来,你需要写:

@foreach($products as $product) 
// Your product block HTML 
@endforeach 
+0

谢谢Raza,我现在正在研究这个问题。 Hopfuly这将解决它。 为了帮助,您如何考虑将产品匹配到恰好2个过滤器? –

+0

已更新我的回答,以描述如何基于提供的产品过滤器过滤独特的产品。 –