Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

SigalZ's avatar

belongsTo from one table to multiple tables

Hello,

I have these 3 tables: order_items, beans, blends

order_items has a field called: product_id

product_id can be a bean or a blend.

Do I do the relationships like this?

orderItem Model:

    public function bean()
    {
        return $this->belongsTo(Bean::class);
    }

    public function blend()
    {
        return $this->belongsTo(Blend::class);
    }

And in Bean and Blend Models:

public function orderItems()
{
        return $this->hasMany(OrderItem::class, 'product_id');
 }

Thanks

0 likes
20 replies
SigalZ's avatar

Hi @mohamedtammam I don't 100% understand these relationships. I hope you don't mind helping me a bit more.

I don't understand how will I get the product name from the order_items table for example.

How will it know if it needs to find the name in the beans table or the blends table?

I tried a few things, and I guess you can see by my tries that I don't really understand this: 1.

//In OrderItem Model
public function product()
{
        return $this->morphTo();
 }

//In Bean and Blend Models:
 public function orderItems()
 {
        return $this->morphMany(OrderItem::class, 'product_id');
  }

I also tried:

//In Bean and Blend models:
 public function orderItems()
 {
        return $this->morphMany(OrderItem::class, 'product');
  }

Going through all the order_items for an order and try to get the product's name:

$items = OrderItem::where('order_id', 1)->get();

foreach($items as $item) {
       echo "<p>" . $item->product->name . "</p>";
}

I also tried:

foreach($items as $item) {
       echo "<p>" . $item->product . "</p>";
}

With all the tries I get this error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'order_items.' in 'where clause' (SQL: select * from order_items where order_items.`` = 2 limit 1)

Can you please help?

SigalZ's avatar

@Tray2 Thank you, but I did not say an item is not an item. I asked how do I get the item's name when an item can be in 2 different tables. It can be in a table called beans and in a table called blends.

MohamedTammam's avatar

@SigalZ Make sure to add item_id and item_type columns in your order_items table.

If you want to make their names become product_id and product_type you can do it like that.

//In OrderItem Model
public function product()
{
        return $this->morphTo(__FUNCTION__, 'product_type', 'product_id');
 }
//In Bean and Blend Models:
 public function orderItems()
 {
        return $this->morphMany(OrderItem::class, 'product');
  }
1 like
pranayb2773's avatar
Level 6

@SigalZ First you need to change order_items table column to support polymorphic relationship. In your migration file, you need to update, product_id column to like this below

$table->morphs('productable', 'produtable_index');

It will generate two columns, producatable_type, productable_id.

  1. productable_type column store model,
  2. productable_type column store model primary key.

In your 'OrderItem` model, add relationship like this

public function productable()
{
     return $this->morphTo();
}

In your Bean & Blend models, add relationship like this

public function OrderItems(): MorphMany
    {
        return $this->morphMany(OrderItem::class, 'produtable');
    }

If order_id is primary key in you order_items table, then you can use it with eargar loading to fetch related tables data also.

OrderItem::with('produtable')->firstWhere('order_id', 1);

Hope this will help you.

1 like
SigalZ's avatar

@Tray2 Thank you, but I'm not sure it will make things simpler.

Is there a way I can contact you privately?

SigalZ's avatar

@Tray2 Thank you but I'm interested in a personal online help with my database and the issues I am facing.

That's why I wanted to chat with you privately and see if you are interested in a paid sessions.

SigalZ's avatar

@Tray2 hi again. I read your article. Very well written, thank you very much. But, I now have new questions. I hope nobody minds me asking here.

What do you do when some of your products have relationships with other tables. Then you can't store it as property/value.

For example, I have bean product that has relationship to roast_types, countries and stickers tables.

Blend product that has the same fields as bean but not the roast_types and countries relationships.

And Coffee_flask that does not have relationship to any table.

So I created product types table as well now and a beans table but I'm getting all mixed up again.

Also, how do you create a form for the user to create a product when you don't know which fields each product has. Product_properties table doesn't specify the field types.

So, I guess you can see, I'm getting very confused trying to use your way.

Thank you for taking the time to read my questions and answering.

SigalZ's avatar

@Tray2 Thx, I'm not sure I'm following you.

one table with allowed properties for each kind of product and then keep the product properties like described above.

I have products table. Keep the product properties like described above? But then again, where do I keep the relationships fields.

Agh, never mind, Thx for trying to help.

SigalZ's avatar

@mohamedtammam @pranayb2773 Thanks guys.

I have these 2 fields in order_items table:

productable_type

productable_id

In my models:

//OrderItem Model
public function productable()
{
        return $this->morphTo();
}

//In Bean and Blend Models
public function orderItems()
{
      return $this->morphMany(OrderItem::class, 'productable');
}

The data I have in order_items:

id = 1

order_id = 1

produactable_type = 'blend'

productable_id = 2

Now if I try:

$items = OrderItem::with('productable')->where('order_id', 1)->get();

foreach($items as $item) {
      dd($item->productable);
}

I get null.

If I try:

dd($item);

I see: relations: array:1 [▼ "productable" => null ]

I changed the data in the productable_type field to 'blends' didn't help either, still getting null.

SigalZ's avatar

Tried this as well:

//OrderItem Model
public function productable()
    {
        return $this->morphTo(__FUNCTION__, 'productable_type', 'productable_id');        
    }

Still getting null.

SigalZ's avatar

And for testing purposes, I create a new table called: comments with these fields:

id

commentable_type

commentable_id

comment

I created a record: id = 1

commentable_type = 'blend'

commentable_id = 2

comment = 'Testing'

In the models:

//Comment Model
public function commentable()
    {
        return $this->morphTo();
        
    }

//Blend model
public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');      
    }

Tried this:

 $c = Comment::find(1);
dd($c->commentable);

Got this error:

Class 'blend' not found

Tried to change the 'commentable_type' field to 'blends' and to 'Blend'

got error: Class 'blends' not found. or Class 'Blend' not found.

SigalZ's avatar

AH!!!, found it, the commentable_type field should have this value in it:

'App\Models\Blend'

Wow, didn't see it in the documentation until now.

Thank you very much guys.

Please or to participate in this conversation.