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

laravel4fun's avatar

Notifications issue when using ShouldQueue / Queueable

Hey all,

Encountered a problem and I'm wondering if you have experienced this before and whether this is a bug or a misunderstanding on my part.

My query:

$leaderboards = \App\Models\Leaderboard::with(['event', 'user', 'league', 'league.myFighters' => function ($query) {
    $query->where('my_fighters.user_id', 1);
}])
    ->where('event_id', 60)
    ->where(function ($query) {
        $query->where('global_champion', true);
        $query->orWhere('league_champion', true);
    })
    ->where('user_id', 1)
    ->get();

In short, I'm retrieving all leaderboards with the child 'league' and the child of the child 'league.myFighters'. When I dump this the results of this query, it's exactly what I expect. Only 'league.myFighters' records with a user_id = 1 are included in the result.

However, when I run:

foreach ($leaderboards as $leaderboard):
    Notification::send(Auth::user(), new WinnerCongratulated($leaderboard));
endforeach;

The data attribute in the notifications table is populated with a leaderboard object where 'league.myFighters' includes items that do not respect the user_id = 1 condition (all myFighter records are included for each leaderboard > league > myFighters).

After some debugging, I found that removing the ShouldQueue / Queueable from the the WinnerCongratulated class resolves the issue and the expected model is saved to the data column in the database. Is there a reason why ShouldQueue / Queueable would change the model I am pushing to my WinnerCongratulated notification object before it saves to the DB?

Is this expected behaviour? Would love to understand!

Thanks so much for your thoughts in advance!

0 likes
2 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

It seems like you're encountering a common issue related to the serialization of Eloquent models when queuing notifications in Laravel. When you dispatch a job to the queue, Laravel serializes the job, including any Eloquent models it contains, to store it in the queue. Upon execution, the job is unserialized and the models are re-retrieved from the database.

The problem you're facing is likely due to the fact that when the WinnerCongratulated notification is serialized, the loaded relationships on the Leaderboard model are also serialized. However, when the job is processed from the queue, the relationships are reloaded from the database without the constraints you initially applied (in this case, the where condition on the my_fighters.user_id).

To resolve this issue, you can explicitly pass only the necessary data to the notification, rather than the entire Eloquent model with its relationships. Here's how you can modify your code:

foreach ($leaderboards as $leaderboard) {
    // Retrieve the necessary data from the model and its relationships
    $data = [
        'leaderboard' => $leaderboard->only(['id', 'user_id', 'league_id', 'event_id', 'points', 'global_champion', 'league_champion']),
        'event' => $leaderboard->event->only(['id', 'name', 'date']),
        'user' => $leaderboard->user->only(['id', 'name']),
        'league' => $leaderboard->league->only(['id', 'name']),
        'my_fighters' => $leaderboard->league->myFighters->map->only(['id', 'user_id', 'league_id', 'discipline', 'gender', 'tone']),
    ];

    // Send the notification with the data array
    Notification::send(Auth::user(), new WinnerCongratulated($data));
}

And then, in your WinnerCongratulated notification, you would accept the data array and use it directly, rather than relying on the Leaderboard model:

class WinnerCongratulated extends Notification implements ShouldQueue
{
    use Queueable;

    private $data;

    public function __construct($data)
    {
        $this->data = $data;
    }

    // Other methods...
}

This way, you're ensuring that only the data you've explicitly passed is used in the notification, and you're avoiding the issue of the entire model being reloaded from the database when the job is processed from the queue.

1 like

Please or to participate in this conversation.