John Davidson

php - Changing an attibute of Laravel Eloquent collection changes every reference

0 comments
Message:


Here's my scenario.
I have a relationship between subscription and product. Every subscription belongs to some product and I have defined relationships.


Now if I do this:
Subscription::with(['product', 'address'])->get();
I will get all subscriptions with product.


Product have attibutes like shipping_price, price etc.


Now if I change shipping_price of a product within a subscription, it changes shipping_price for that product inside all subscriptions (This comes in handy manier times but this time I dont want this change to reflect everywhere).


For example:


$subscriptions = Subscription::with('product')->get();
foreach ($subscriptions as $item) {
$item->product->shipping_price = ShippingService::getShippingPrice($item->product->key, $item->product->shipping_price, $item->address->zip);
}

This will change shipping_price for every product having same ID within those subscriptions.


My requirement is to stop this behavior at this one place. So if I change one attribute, it doesnt change others.


I know one way to query again with loop and dont get products using eager loading but that will be slow.


Thanks.



My Answer:
>get();

This will return a collection of subscriptions with their related product and address. Now, if I want to change an attribute of the product for a specific subscription, I can do so like this:

php
$subscriptions = Subscription::with(['product', 'address'])->get();

foreach ($subscriptions as $subscription) {
$subscription->product->name = 'New Product Name';
}



However, this will change the product name for every subscription in the collection, not just the specific one we are iterating over. This is because Eloquent relationships in Laravel return references to the related models, not copies.

To change the product name for just one subscription, you can do this:

php
$subscription = Subscription::with(['product', 'address'])->first();

$subscription->product->name = 'New Product Name';
$subscription->product->save();


This way, only the product name for the specific subscription will be changed.

Rate this post

5 of 5 based on 7562 votes

Comments




© 2024 Hayatsk.info - Personal Blogs Platform. All Rights Reserved.
Create blog  |  Privacy Policy  |  Terms & Conditions  |  Contact Us