I've experiencing a quite unique case, where, when doing bulk update (using where
condition) from a relationship, it does update every record that match the condition, instead of a single row
Here's the sample code:
// Model
class Customer extends Model
{
protected $table = 'customer';
protected $primaryKey = 'id_cust';
...
...
...
public function customer_address()
{
return $this->hasOne(CustomerAddress::class, 'customer_id', 'id_cust');
}
...
...
...
}
class CustomerAddress extends Model
{
...
...
...
public function customer()
{
return $this->belongsTo(Customer::class, 'customer_id', 'id_cust')->withDefault([
'name' => ''
]);
}
// controller
class CustomerController extends BaseCustomerController
{
...
...
...
/**
* Update the specified resource in storage.
* @param Request $request
* @param Customer $customer
* @return Renderable
*/
public function update(CustomerEditRequest $request, Customer $customer)
{
...
...
...
$insert_address['address_label'] = 'Default';
$insert_address['recipient_name'] = $request->recipient_name;
$insert_address['recipient_phone'] = $request->international_code . '' . $request->recipient_phone;
$insert_address['province_id'] = $request->province_id;
$insert_address['city_id'] = $request->city_id;
$insert_address['district_id'] = $request->district_id;
$insert_address['recipient_address'] = $request->recipient_address;
if ($customer->customer_address) {
$customer->customer_address->where('is_default', '1')->update($insert_address); // ---> here the possible of suspicious code
} else {
CustomerAddress::create([...$insert_address, 'is_default' => '1', 'customer_id' => $customer->id_cust]);
}
...
...
...
}
}
Notice, on CustomerController
, function update
, on this part $customer->customer_address->where('is_default', '1')->update($insert_address);
I'm assuming that, it will only get customer_address
data which related to $customer
, and then update with, with condition is_default = 1
But, instead, it update all data that has is_default = 1
Why it's happening? what's wrong with that?
When I'm using $customer->customer_address->update($insert_address);
, it's correct and only update the related record
If it's indeed can't, how do I can still update it, while persisting ability of where
condition?
For those who stumble upon this same issue (or related to this somehow), after few hours of debugging with my colleagues, I found out that:
If we're using that way, $customer->customer_address->where(...)
, which a direct condition after a relationship, it will pull all the Model data (which is, customer_address
), then filter it by the condition, instead of the data that related to its first relation.
I also try what my colleague suggest (same suggestion from @Takachi here, thanks for that! :)), which using $customer->customer_address()->where(...)
, it will also works, as, it seems, it call the query builder
of the relation, and then, apply the where
condition
After spend some more time to get a documentation & materials on what happening, it seems the way that I've done is expected, here are some references I could found:
Again, I'm using Laravel 9.x version, so quite unsure if this still happened on newer version. But it seems, the same thing still occurred, judging from the documentation on Laravel 10.x
Anyway, thanks for coming here! Especially @Takachi for give me his cents! :)