2017-10-19 6 views
4

Je travaille sur un filtre pour certains produits. J'ai la majorité de cela fonctionne mais je rencontre une erreur avec une clause where impossible.Laravel impossible où requête

La table contient plusieurs lignes pour un seul produit et j'essaie de faire correspondre plusieurs critères par produit, ce qui provoque son échec.

Si vous avez une opinion à ce sujet, ou peut-être un moyen de résoudre ce problème, je l'apprécierais grandement.

La table de base de données ressemble à ceci:

 
    -------------------------------------------- 
    |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   | 
    -------------------------------------------- 

Et le filtre ressemble à ceci:

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; 
} 

Cela affiche alors l'instruction SQL suivante:

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 

Si cette option est sélectionnée, comme dans la capture d'écran, seul le «produit un» doit être présent sur la page.

+0

Ceci est appelé une logique de division.Procédé réglée à suivre est « obtenir un produit pour lequel il n'existe pas un filtre sélectionné que n'a pas " – apokryfos

Répondre

0

La portée que vous avez ajouté à mon avis est erronée. Même votre structure de base de données est incorrecte à mon avis. Voici comment je structurer:

Filtres Tableau

Ce modèle tiendra toutes les valeurs de filtre. Par exemple, Colour, Size etc. Voici comment la table de filtre sera structuré:

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

donc votre modèle éloquent devenir quelque chose comme ceci:

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

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

Produits Tableau

Vos modèles de produits devient:

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

products_filters Tableau

Après les modifications ci-dessus, voici comment la table sera structurée:

-------------------------------------------- 
|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   | 
-------------------------------------------- 

Maintenant, vous pouvez simplement interroger la table filtres, puis obtenir des produits associés pour tous les filtres. Après cela, vous avez simplement besoin de compiler une liste de produits uniques.

Produits uniques basés sur des filtres sélectionnés.

$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')); 

À votre avis, vous devez écrire:

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

Merci Raza, je suis en train de l'implanter maintenant. Hopfuly cela va le résoudre. Pour vous aider, comment envisageriez-vous de tirer un produit à un endroit où il correspond exactement à 2 des filtres? –

+0

Mise à jour de ma réponse pour décrire comment je filtrerais des produits uniques en fonction des filtres de produits fournis. –