Hi @arreguialvaro,
Apologies if you have already done this, but did you create a soft deletes migration on the wallets table?
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
Should a model that is deleted (using soft deletes) be returned when querying it through a related model?
I have a model, User that hasMany Wallet and when I call $user->wallets, that deleted model (Wallet) is listed in the results...
Do I really need to use $user->wallets()->whereNull('deleted_at')->get()?
use Illuminate\Database\Eloquent\SoftDeletes;
class Wallet extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
}
Hi @arreguialvaro,
Apologies if you have already done this, but did you create a soft deletes migration on the wallets table?
No worries @desloc yes, thats already included. These are the attributes returned by $user->wallets
#attributes: array:8 [
"id" => 1
"user_id" => 60
"token" => "xcZjdEzBzQNYTDy6EtQGRssgtN2LuGa1Vh-F0p79CEcAABhSW9W0gj5k6vzOe8aJBwUZ7AAAAAEAAAHp"
"masked_pan" => "****************"
"created_at" => "2017-03-08 11:52:26"
"updated_at" => "2017-03-17 10:34:41"
"deleted_at" => "2017-03-17 10:34:41"
"alias" => "My Wallet"
]
What if you comment out your protected $dates line
@Snapey That won´t help...
Here's my complete model:
<?php
namespace App\Models\EWallet;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Card extends Model
{
use SoftDeletes;
protected $connection = 'main';
protected $fillable = ['alias', 'token', 'masked_pan'];
protected $dates = ['deleted_at'];
protected static function boot()
{
static::deleted(function ($card) {
$card->top_ups()->delete();
});
}
public function top_ups()
{
return $this->hasMany(ScheduledTopUp::class);
}
}
$ php artisan tinker
Psy Shell v0.8.2 (PHP 5.6.29 — cli) by Justin Hileman
>>> use App\Models\Billpocket\User; $user = User::find(60)->cards;
=> Illuminate\Database\Eloquent\Collection {#708
all: [
App\Models\EWallet\Card {#707
id: 1,
user_id: 60,
token: "xcZjdEzBzQNYTDy6EtQGRssgtN2LuGa1Vh-F0p79CEcAABhSW9W0gj5k6vzOe8aJBwUZ7AAAAAEAAAHp",
masked_pan: "****************",
created_at: "2017-03-08 11:52:26",
updated_at: "2017-03-17 10:34:41",
deleted_at: "2017-03-17 10:34:41",
alias: "My Card",
},
],
}
>>>
Why won't it help? and what has the rest of the model got to do with it?
@Snapey If I'm not mistaken, $dates only indicates what fields should be mutated to an instance of Carbon
Anyways, I tried your suggestion and still got the same result.
I added the rest of the model just for clarification, forgive me for being out of line.
ok no worries. it's related to deleted_at so could be linked. for the few seconds it takes to try I thought it might be worth a shot.
I cannot remember adding it to dates when i used soft deletes in the past but i can see it us recommended in the docs.
A few things to try
if you do Card::all() are deleted included?
do you have $with in your User model?
Yes, Card::all(); returns deleted models...
I'm not sure what you mean by $with, this is the relationship in the User model:
public function cards()
{
return $this->hasMany(Card::class);
}
i'm wondering why the scope could be bypassed, so Card::all() is to eliminate any interference from the User model
the other question, with is because you can have a $with array in another model and it will automatically eager load relations. I thought if you had $with(['card']) in your User model it might be bypassing the scope
The only thing I can suggest at this point is to review the sql query that is used
Hi @arreguialvaro ,
I think I encountered this issue my self once, try removing deleted_at from the $dates array.
Just looking through the code... Just out of interest, are your table names standard, e.g. cards and wallets?
Hi there @arreguialvaro did you find a solution for this, I think I am experiencing this issue as well.
+1 for this...
Found out why it wasn't working on my end, apparently it does not work well if you have included other traits that modify the scope. The issue is not the same symptom, but it is the same reason: https://github.com/laravel/framework/issues/9349
You can circumvent it by using the soft delete trait in your custom trait that adds a global scope:
use SoftDeletes;
public static function boot()
{
static::addGlobalScope(function (Builder $builder) {
// Add custom scope here
});
static::bootSoftDeletes();
}
@Coreation that is correct, you need to boot the soft deletes inside the model if you are overriding the boot method.
protected static function boot()
{
parent::boot();
static::deleted(function ($card) {
$card->top_ups()->delete();
});
}
@COREATION - Thanks for this!
Please or to participate in this conversation.