I'm building a layered navigation module for my laravel application - Much like is done in Magento or WooCommerce. This is the idea: Products can be assigned single or multiple attributes and users then should be able to filter the products down by using these attributes. Like the attribute "material" where products can be assigned one or more values like iron, wood & plastic. My problem is that I can't figure out how to do this properly.
My datamodel is like this:
products table: id | name | other info...
example: 42 | Chair | ...
example: 14 | Bike | ...
attributes table: id | name | description
example: 02 | Material | the material that the...
attribute_options table: id | attribute_id | value
example: 11 | 02 | Wood
example: 12 | 02 | Iron
pivot table: id | product_id | attribute_option_id
example: 12 | 42 | 11
example: 12 | 42 | 12
example: 12 | 14 | 12
I've set a many to many relation between the Product and Product Option models (hence the pivot table).
In my view file a form is displayed which loops over all the different attributes and then loops over their options and creates a checkbox for each of the options with a value of their id's. The values are ideally grouped together in one array and named like this: filter[attribute_id][attribute_option_id]. An example:
<input type="checkbox" name="filter[02][11]" value="id"> Wood
<input type="checkbox" name="filter[02][12]" value="id"> Iron
<input type="checkbox" name="filter[xx][xx]" value="id"> Etc..
On submitting the form all the selected attribute option values are send to the server to a route where this information should be processed and only products that meet all different criteria should be returned.
So if filters[02][11] and [02][12] would be posted, only products should be returned that have the attribute options of "Wood" and "Iron" assigned.
At first, I thought this would be quite simple, but I think I'm not as skilled as I thought I would be... Since this is a Laravel question, I'd love for a eloquent style solution!
P.S. If I messed up the (thinking behind my) datamodel, please tell me! I'm still learning a lot of stuff about web development and maybe there is a much better/cleaner solution/approach to my problem
-------- EDIT / ADDITIONAL INFORMATION --------
With the following code I can filter for one attribute
$products = $products->whereHas('attributeOptions', function($query)
{
$query->where(function($query)
{
$query->where('value', 'iron');
});
});
But since products can have multiple attributes of different types (like color and material or multiple materials) I need to be able to set multiple wheres like this:
$products = $products->whereHas('attributeOptions', function($query)
{
$query->where(function($query)
{
$query->where('value', 'iron');
$query->where('value', 'wood');
$query->where('value', 'yellow');
});
});
But this code doesn't work since it checks for one row having multiple values instead of checking for values on multiple rows with the same product_id.
The relation between products and attribute_options is:
public function attributeOptions() {
return $this->belongsToMany('AttributeOption', 'products_attribute_options', 'product_id', 'attribute_option_id');
}
Is this even possible in Eloquent/Laravel or do I need a different solution
Thanks in advance, I'd love to learn from you!