Reputation:
I would like to get all products related to a certian color using Eloquent 'hasMany' relationship. However the colors related to products are stored in json
value in the products table.
Color Table:
-------------
id | color
-------------
1 Black
2 Brown
3 Gray
Product Table:
------------------------------
id | name | color
------------------------------
1 Shoe Name ["1","2"]
2 Shoe Name ["2","3"]
Color Model
public function products()
{
return $this->hasMany(Product::class, 'color');
}
But unfortunately nothing returns when i do
dd(Color::products());
I know the issue is trying to do a hasMany
on a json field, any help or assistance would be great. Unfortunately i won't be able to change the database structure. I need to work with it as is.
Thanks in advance.
Upvotes: 6
Views: 21757
Reputation: 25926
I created a package with JSON relationships: https://github.com/staudenmeir/eloquent-json-relations
You can create a many-to-many relationship like this:
class Product extends Model
{
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
protected $casts = [
'color' => 'json'
];
public function colors()
{
return $this->belongsToJson(Color::class, 'color');
}
}
class Color extends Model
{
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
public function products()
{
return $this->hasManyJson(Product::class, 'color');
}
}
Upvotes: 21
Reputation: 941
Going on from my comment, ideally i would simply do the following:
product_colors
to store product & color association. So the relation will become a many-to-many. This i would seriously recommend. Since you have written that you aren't able to alter the database structure.
For example, to retrieve list of products for a color. Your solution might be something like the following:
public function setColor()
{
return json_decode($this->color, true);
}
public function products()
{
return Product::all()->filter(function($product) {
return in_array($this->id, $product->color)) ? $product : null;
});
}
Upvotes: 7