One-to-Many relationship between multiple tables - laravel

I'm trying to make a relationship between Product and Brand models with an intermediate model BrandProduct, intermediate model also contains some additional info like product_model etc.
My aim is to access all the products that belong to a specific brand with additional manufacturer info and also I want to access the brand of a specific product with additional info.
I've a Model named Product with these attributes
id
name
sku
quantity
etc.....
Another Model named Brand with following attributes
id
name
logo
And an intermediate Model named BrandProduct with attributes
id
brand_id
product_id
model
etc.....
I'm registering Brands and Products separately and making a relationship between them by BrandProduct Model with additional attributes like product_model.
Brand.php model contains:
public function products(){
return $this->hasMany('App\Models\BrandProduct');
}
Product.php model contains:
public function manufacturer(){
return $this->hasOne('App\Models\BrandProduct');
}
And BrandProduct.php model contains:
public function data(){
return $this->belongsTo('App\Models\Product', 'product_id', 'id');
}
public function brand(){
return $this->belongsTo('App\Models\Brand', 'brand_id', 'id');
}
Now I can successfully retrieve Product > Manufacturer by
$p = Product::find(id)->manufacturer
But I can't get inverse relation BrandProduct > Data by trying
$p = BrandProduct::find(id)->data
Similarly I can retrieve all the Brand > Products by
$p = Brand::find(id)->products
But can't get inverse relation
$b = BrandProduct::find(id)->brand
In the end I'd like to achieve something like this:
//For Brand > Products
$p = Brand::find(id)->products;
$product_model = $p[0]->model;
$product_name = $p[0]->data->name;
//For Product > Manufacturer
$p = Product::find(id)->manufacturer;
$product_model = $p->model;
$brand_name = $p->brand->name;
Please tell me what's wrong with my approach all other relationships are working fine except this one.

Related

laravel has many through piviot table

I have 3 tables
Products
id, name, image
Offers
id,name
Offer_product
id,offer_id,product_id
I am accessing data of product table with pagination using
$list = Product::query()->paginate(6);
now i want the complete record of products with offer name stored in offers table . id of both product and offers are stored in offer_product table where one products can have many offers
In your DB design you have a Many-to-Many relation, which in Laravel is handle by belongsToMany https://laravel.com/docs/5.7/eloquent-relationships#many-to-many.
hasManyThrough is for cascade 1-to-Many -> 1-to-Many case. Let's say an Artist has many Albums and each Album has many Songs, then an Artist has many Songs through Albums. If you need an Artist Songs, then you may use directly hasManyThrough.
In your case your relation in Product.php model should be :
public function offers() {
return $this->belongsToMany(Offer::class, 'Offer_product')->withPivot('id');
}
In Offer.php model :
public function products() {
return $this->belongsToMany(Product::class, 'Offer_product')->withPivot('id');
}
Now if you want all of them with eager loading https://laravel.com/docs/5.7/eloquent-relationships#eager-loading to avoid N(products)+1 calls to database :
$products = Product::with('offers')->get();
foreach ($products as $product) {
echo 'product : '.$product->name.'<br/>';
foreach($product->offers as $offer) {
echo '<br>---- offer : '.$offer->name;
// once you called the relation, then you can access data on pivot table
echo ' - pivot id :'.$offer->pivot->id;
}
}

Laravel Fetching one to Many Relationship

Hello I am learning laravel and I am having an issue retrieving data from my relations.
In my database there are Product and Groups filled with dummy data.
I defined my relationship like this in product model:
public function Group()
{
return $this->hasMany('App\Groups','product_id', 'id');
}
And in my group vice versa with :
public function Product()
{
return $this->belongsTo('App\Product','product_id', 'id');
}
The way I am referencing to my products table is :
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
Now I have column product_id in my database under groups, and it is linked to if from products id it seems.
The groups table contains of its auto incremented id and product_id foreign key column.
While products table has auto incremented id and name column.
The issue is here :
How do I return the products that are not null or have value (of products id) in groups table.
I tried something like this in my filter controller:
public function getProductsWithGroup()
{
$Products = Product::with('groups')->get();
return $Products ;
}
But that is giving me call to undefined relations.
I am not sure how to access belongsTo or hasMany methods and whether I need an extra group_id column in my products table.
You named the relationship wrong. It should be groups & define in lowercase as
public function groups()
{
return $this->hasMany('App\Groups','product_id', 'id');
}
And use ->has() to check existence
public function getProductsWithGroup()
{
$Products = Product::has('groups')->get();
return $Products ;
}
->with() is used to eager load and ->has() is used to check existence & filter.
To get the products don't have any groups,
$Products = Product::doesntHave('groups')->get();
To see other ways to use ->has() check, https://laravel.com/docs/5.7/eloquent-relationships#querying-relationship-existence

Laravel 5 multi level category

i currently i have 2 tables category & subcategory and everything works just fine, but i need another level of sub category which will be like category->sub->sub for that matter i tried to find a reasonable solution and i end up with bunch of packages to handle that for me.
now the question is
do i have to delete my category tables and their relations to my
another modes before i try any package or i should just add package top of my current tables?
what is the best package for my purpose base on your experience?
thanks in advance.
You don't need to depend on packages to implement this.
You can design your categories table like following:
|----------|------------|---------------|
| id | name | category_id |
|----------|------------|---------------|
Here category_id is nullable field and foreign key referenced to id of categories table.
For category category_id field will be NULL and for sub-category category_id will be it's parent category id. For sub sub category, category_id will be parent sub category id.
In model, you can write relation like following:
Category.php
/**
* Get the sub categories for the category.
*/
public function categories()
{
return $this->hasMany(Category::class);
}
Now you can get your sub categories like $category->categories.
N.B: You don't need the subcategory table, Only one table will do the work.
Update- Show product categories
Update Category.php:
/**
* Get the parent category that owns the category.
*/
public function parent()
{
return $this->belongsTo(Category::class);
}
In Product.php:
/**
* Get the category that owns the product.
*/
public function category()
{
return $this->belongsTo(Category::class);
}
Now, you need to get product category and all of its parents. It'll be an array of categories from parents to child. Then you can show as you wish.
$category = $product->category;
$categories = [$category];
while (!is_null($category) && !is_null($category = $category->parent)) {
$categories.unshift($category);
}
// $categories = ['parent category', 'sub category', 'sub sub category' ..]
Show category title sequentially
foreach ($categories as $category) {
echo $category->title . '<br>';
}

Getting an ID from Pivot table Eloquent belongsToMany() - Laravel 5.2

I have two items. Shops & Categories. In my Shop model I have declared this relation :
public function categories()
{
return $this->belongsToMany('App\Models\Category');
}
and in my Category model I have this :
public function shops()
{
return $this->belongsToMany('App\Models\Shop');
}
I am able to add Shop in to category by using attach. For example this code :
$shop->categories()->attach($cat_id);
By using the above attach method, a record is automatically created in my pivot table category_shop with category_id and shop_id.
Now, I have a shop loaded to $shop. Like below :
$shop = Shop::findOrFail($id);
Obviously now I have my shop id in $shop->id. My question is how can I get back the category id(s) of this shop by using the above setup.? I am new to laravel.
Since, shop has many categories. You will get many categories id.
$shop= Shop::findOrFail($id);
foreach($shop->categories as $category)
{
print_r($category->id);
}

Laravel Get products from multiple taxonomies

I have 3 tables, products, taxonomies and product_taxonomy. The 3rd table is a pivot table that contains product_id and taxonomy_id, meaning that product and taxonomy are many to many relationship. Given a list of taxonomy ids, how can I get all the products that belong to these taxonomies? NOTE: I want to have the products result set being able to paginated or order by maybe it's price or something.
You need to create many-to-many relationship and that requires relationship methods like:
// Product Model
public function taxonomies()
{
return $this->belongsToMany('Taxonomy');
}
// Taxonomy Model
public function products()
{
return $this->belongsToMany('Product');
}
The query:
$listOfTaxonomyIds = [1,2,3];
$products = Product::whereHas('taxonomies', function($query) use ($listOfTaxonomyIds){
$query->whereIn('taxonomy_id', $listOfTaxonomyIds);
})->get();

Resources