简体   繁体   中英

Laravel 4.2 returning soft deleted on BelongsToMany results

Hello I just noticed one weird behaviour of softDelete. Basically, when I query for a related set of models, Eloquent returns a collection that also contains soft deleted rows.

I have been following the 4.2 guides on traits usage for softdelete and my code works just fine as long as I get/delete/restore/force delete my models. The issue is triggered with relations.

Consider this scenario: I have a user model that has a belongToMany friendship relation where the friendship status can be accepted/pending/requested/blocked as follows:

public function friends() {
     return $this->belongsToMany('User', 'friends', 'user_id', 'friend_id')->where('status', 'accepted');
}

This friends table rows are basically "vectors" where user1->status->user2 and viceversa (user2->status->user1 is on another row). When user1 decides not to be friend with user2 anymore, the 2 friends rows are softdeleted.

Here is the issue: when I query the DB from the controller like this:

$friends = $user->friends;

even the softdeleted rows show up in the returned collection even though I would have expected these to be hidden from results unless I used ->withTrashed().

I suspect the belongsToMany() method doesn't take into account the deleted_at field on the pivot table.

Did anyone faced a similar issue? Am I doing something wrong with this relation?

Thanks a lot for your help!!!

Adding:

->whereNull('friends.deleted_at')

to my model friends() method seems to solve my issue easily (silly me for not thinking about it a few minutes earlier). I would have expected Eloquent to be able to properly deal with these softdeleted pivot rows.

Still I wonder if I am misunderstanding how to use these relations...

I'm assuming you have a Friend model that uses the SoftDeletingTrait .

Soft deleting is a function of the Model. However, the BelongsToMany relationship doesn't require a model to be defined for the pivot table, so it doesn't take into account a Model even if it exists. It works with the base table. Since the relationship doesn't know about any model connected to the pivot table, it doesn't know about soft deleting on the pivot table.

Your current solution may fine, but you may want to consider using wherePivot instead:

->wherePivot('deleted_at', null)
// or
->wherePivot(Friend::getDeletedAtColumn(), null)

This way, the soft deleting clause is used for any other internal relationship processing that ends up building new queries specifically for the pivot table (eg sync, detach, updateExistingPivot, etc.).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM