Laravel Eloquent many to many relationship with different column as key - php

I have the following models
Category
id // we don't want to use this one for the relation
category_id // we want to use this
Product
id
CategoryProduct
product_id // points to "id" on products table
category_id // points to **category_id** on categories table
I have the Product model set up as follows (only the most recent variation).
class Product {
public function categories() {
return $this->belongsToMany('Category', 'categories_products', 'category_id');
}
}
When I try to get a product with categories as follows...
Product::with('categories')->get();
I either get the wrong categories because the query is using id on categories as the foreign key. I need it to be using category_id on the categories table.
Or I get none at all. I can't seem to hash out how to set up which columns to use on the belongsToMany method.

Try this follow,
class Product {
public function categories() {
return $this->belongsToMany('Category', 'categories_products', 'product_id','category_id');
}
}

Related

fetch join table data using eloquent laravel

I am new to laravel & want to implement eloquent relationship.
Let me explain.
Consider I have 2 tables
products
product_id
product_name
brand_id
price
brands
id
brand_name
Each product will have one brand Id.But in Brands table, there is no product id. One brand_id can be in multiple product rows, and one product has one brand_id only. I want to select some col from products table plus brand_name with respect to brand_id of products table using Model.SO in Product model I wrote:
public function brands()
{
return $this->hasOne('App\Brand','product_id');
}
and in Brand model I write:
public function products()
{
return $this->belongsTo('App\Product','brand_id');
}
Now I want the result:
product_name
price
brand_name
How can I fetch those data in controller using eloquent relation? Also, the way I wrote Model relationship, Is it ok??
Your Product Model relation will be below
public function brand(){
return $this->belongsTo('App\Brand','brand_id');
}
public function product(){
return $this->belongsTo('App\Product','product_id');
}
Now in controller you can add query as below.
$products = Product::with('brand','product')->get();
echo '<pre>'
print_r($products->toArray());
exit;
It looks to me like you want a one-to-many relationship, so one brand can have many products and many products belong to one brand.
Product model:
public function brand()
{
return $this->belongsTo('App\Brand');
}
Brand model:
public function products()
{
return $this->hasMany('App\Product');
}
Then you would be able to get the brand information like this:
The full brand model:
Product::first()->brand
The brand name:
Product::first()->brand->brand_name
From the docs:
A one-to-many relationship is used to define relationships where a
single model owns any amount of other models. For example, a blog post
may have an infinite number of comments.
P.S.:
Your table column names do not make much sense to me, why do you have product_id on products but then on brands it is just called id? Why do you have product_name but then just price? why is it not just name or product_price, so your at least consistent?

Laravel "with" is not populate related model

I have two tables in Laravel Eloquent:
UserCategory:
id | user | category
and
Category:
id | name
UserCategories relates to Category trough belongsTo:
class UserCategory extends Model
{
public function category()
{
return $this->belongsTo('App\Category', 'category');
}
}
But when I try to get UserCategories with Categories I got integer value (instead of Category model)
$categories = [];
$userCategory = UserCategory::where('user', $user->id)->with('category')->get();
foreach($userCategory as $item) {
$categories[] = $item->category->name;
}
When I try to get the category's name I see the second error:
Trying to get property 'name' of non-object
Curious thing, that when I use dd($item) I see that $item has correct relation to Category object, but dd($item->category) returns integer value (category id) instead of category model.
You have conflicting names. You have both a category column, and a category relationship. By saying $item->category its showing you the category column value. Try changing the relationship name to something else and see if that works.
The best practice would be to use a column name of category_id, but if changing the column name isn't feasible in your situation then the relationship name will work just as well.
Change your relation name or id name here because here your relation name & coloumn name is same
class UserCategory extends Model
{
public function category()
{
return $this->belongsTo(Category::class, 'category');
}
}

Sum pivot table field on Eloquent many-to-many relationship

I have an orders table, an items table, and a pivot table called item_order which has two custom fields (price, quantity). The relationship between Order and Item is belongsToMany. I'm trying to return the count of all items with an id of 1, where the parent Order->status == 'received'. For the life of me, I can't figure out how to do this.
class Order extends Model
{
public function items()
{
return $this->belongsToMany(Item::class)->withPivot('price', 'quantity');
}
}
class Item extends Model
{
public function orders()
{
return $this->belongsToMany(Order::class)->withPivot('price', 'quantity');
}
}
Try this:
$total_quantity = Item::find(1) // getting the Item
->orders() // entering the relationship
->with('items') // eager loading related data
->where('status', '=', 'received') // constraining the relationship
->get() // getting the results: Collection of Order
->sum('pivot.quantity'); // sum the pivot field to return a single value.
The strategy here is to find the desired Item to then get the related Orders to this Item that has a 'received' status, to finally sum the pivot attribute in order to get a single value.
It should work.
Considering you know the id of the item, most performant way would be to query item_order table directly. I would create a pivot model for ItemOrder and define the belongsTo(Order::class) relationship and do this:
$sum = ItemOrder::where('item_id', $someItemId)
->whereHas('order', function ($q) {
return $q->where('status', 'received');
})
->sum('quantity');

Eloquent many to many relationship access table column value from pivot table

I have two models:
class Order extends Eloquent
{
public function User()
{
return $this->belongsTo('User');
}
public function Product()
{
return $this->belongsToMany('Product');
}
}
and the second one is:
class Product extends Eloquent
{
public function Order()
{
return $this->belongsToMany('Order');
}
}
My question is how can i access a value of second table column using pivot table:
product table:
id
title
image
order table:
id
status
pivot table(order_product):
id
product_id
order_id
I need to access title column of products from orders. for example if a user orders many products in one order I can fetch all product title and show theme.
I don't like use join , instead I like to use Laravel functionality itself.
I found the answer:
$orders = Order::orderBy('created_at', 'DESC')->paginate($page_number);
foreach($orders as $item){
foreach($item->product as $item){
{{$item->title}}<br>
}
}
I can access products from order.

Laravel Eloquent with()-> returning null

I am trying to use Eloquent to get a specific product that has a brand_id column that maps to a brands table, the brand array is coming back empty.
Is there anything obvious here that needs to be changed?
$product = Product::with('images')->with('brand')->select($fields)->where('display', '=', 1)->find($id);
//Product model
class Product extends Eloquent {
...
public function brand()
{
return $this->belongsTo('Brand');
}
//Brand model
class Brand extends Eloquent {
...
public function products()
{
return $this->hasMany('Product');
}
You have this:
$product = Product::with('images', 'brand')
->select($fields)
->where('display', 1)
->find($id);
You are getting null for brand and it could be because you have some specific fields and most probably you didn't select the foreing_key from the products table that creates the relationship with Brand, so if your products table contains the foreign_key (probably brand_id) of brand table then you have to select that foreign_key from the products table too. So, just add that foreign_key/brand_id in the $fields variable. Without the relation builder key (FK) the Brand won't be loaded.

Categories