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

t0berius's avatar

attach() / associate() not working as expected

I'm planning to assign stockItemsto an order

product:

public function stockItems()
{
    return $this->hasMany('App\ProductStockItem');
}

order:

public function stockItems()
{
    return $this->hasMany('App\ProductStockItem');
}

public function product(){

    return $this->belongsTo('App\Product', 'product_id', 'id')->withTrashed();
}

stockItem:

public function product()
{
    return $this->belongsTo('App\Product');
}
public function order()
{
    return $this->belongsTo('App\Order');
}

Controller code:

$order = Order::find(2);

    $items = $order->product->stockItems()->available()->take(2)->get();

    $order->stockItems()->attach($items);

For some reason I get Illuminate\Database\Eloquent\Relations\HasMany::attach(). Isn't attach the correct method for this?

0 likes
18 replies
t0berius's avatar

@deansatch Still Call to undefined method Illuminate\Database\Eloquent\Relations\HasMany::attach(), the typo was caused by editing here on laracasts.

deansatch's avatar

try changing this on Order model:


public function stockItems()
{
    return $this->belongsToMany('App\ProductStockItem');
}

t0berius's avatar

@deansatch I've tried this on product and on order model, one by one. Doesn't help to solve the problem, a belongsToManyrelation is somehow wrong anyways isn't it?

deansatch's avatar

No they should both be belongsToMany if it is a many to many relationship. Ah...I've just noticed it isn't. In that case I don't think attach() will work for this. Maybe this is what you need...


    	$order->stockItems()->saveMany($items);

t0berius's avatar

@deansatch Is there any way I can link a stockItem easily to an order? StockItems represent a virtual access, so I would need to assign it to an order, when order is not paid within a certain timeframe I would need to remove this relation again, so attach() and associate() sound great, but none of them is working for this?

UsmanBasharmal's avatar

The attach() method is only for many-to-many, for other relationships, there's save() or saveMany() and associate() .

deansatch's avatar

I can't really tell what you are trying to do with your db setup but I think you just nee to rethink your relationships so they make a bit more sense. e.g. I would expect an order to have many (hasMany) products rather than the other way round which is what you have. Then you can add products to an order and remove them at any point - not sure what the stockItems table is all about though

t0berius's avatar

saveMany() works. Is there a method to remove the assigned relations?

@deansatch An order is only related to a single product, this is fine for me. Any idea regarding how to remove the relation, created by saveMany()?

deansatch's avatar
$order->stockItems()->dissociate();
$order->save();
t0berius's avatar

Resulting in Illuminate\Database\Eloquent\Relations\HasMany::dissociate(), same as with associate().

deansatch's avatar

ah yeah...that is for a belongsTo relationship also. This is where I'm getting confused because logically that is what they should be. It would probably have to just be another saveMany() but with your default values instead of the Order IDs

t0berius's avatar

I included the relations of stockItem into my first post too.

deansatch's avatar

Surely you just need to delete those stockitems from the stock_items table? If I understand correctly you are copying a product from the products table and saving it as a stockItem connected to an order. So to break that association you just need to delete those stock items. So something like this:

$order->stockItems()->delete();

t0berius's avatar

@deansatch

A product can have many StockItems. An order can contain exactly one product. An order can contain many StockItems.

When an order is created the StockItems are assigned to this order order_id on stockItems model. If this order is not payed in full in X hours the relation should be deleted (order_idset to null) again.

Hopes this makes it a bit clearer.

deansatch's avatar

StockItem::where('order_id', $order_id)->update(['order_id' => NULL]);

t0berius's avatar

@deansatch I know, thought there would be a more elegant way, using eloquent relation methods.

deansatch's avatar

That probably is the most elegant way - there is no need to query the orders table to do this so just do it directly. The method that fires most probably already has the order_id as an argument so that would be all that is needed

Please or to participate in this conversation.