framework: Queued notification model serialization problem
- Laravel Version: 5.3.18
- PHP Version: 7.0.5
Description:
When a Notification is set to queue (it implements ShouldQueue, Queueable, SerializesModels) the via($notifiable)
method doesn’t accept a call to a model passed into the notification constructor by returning a Undefined property: Illuminate\Contracts\Database\ModelIdentifier::$property
Steps To Reproduce:
create a notification
class MyNotification extends Notification implements ShouldQueue
{
use Queueable;
use SerializesModels;
public $model;
public function __construct($model)
{
$this->model = $model;
}
public function via($notifiable)
{
if($this->model->property == 1) {
return ['mail'];
}
return [];
}
}
call a notification via
Notification::send($users, new MyNotification($model));
get a Undefined property: Illuminate\Contracts\Database\ModelIdentifier::$property
error
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 2
- Comments: 35 (15 by maintainers)
I found the problem, you need to define it as protected in the notification class, like this:
I hope this helps.
i have same issue, and i resolved, i juste remove SerializesModels in my classJob and the queue work fine
@lucadegasperi can you help me replicate? on a fresh installation can you replicate the issue?
Not sure why this was closed, as it’s not fixed.
I’ve just spent hours tracking this issue down. After adding
implements ShouldQueue
to my notification, the model attributes are lost in the toMail and toArray methods:I’m passing a model to the constructor and setting a public (or private/protected… makes no differernce) property. If I dump the model from the constructor, all attributes are there as expected, but if I dump the model from the
toMail
method, attributes are missing.Obviously removing
implements ShouldQueue
fixes the problem, but slows the system. Is there a fix that doesn’t involve changes to Laravel source?I just experienced this problem myself. The problem was because my queue processor was still running the old code after deploying. You specifically need to terminate and restart your queue after your new code is released. If you’re using horizon f.e. you need to run
horizon:purge
&horizon:terminate
right after activating a new release. That should be enough for your jobs to work properly with theSerializesModels
trait.When sending the notification to multiple users (and getting the error above) what I saw is that the first time the
via()
method gets called it’s an instance of the model, the second time it’s an instance ofIlluminate\Contracts\Database\ModelIdentifier
this led me to believe there was a problem with the serialization / deserialization that happens when a notification is dispatched onto the bus.See also https://github.com/laravel/framework/issues/26791 for more info about my issue how to reproduce and how to solve it.
@akalongman it prunes orphaned Horizon processes which aren’t managed anymore.
I had the same issue when I had an event that fired 2 listeners. Each listener did not have any queue, instead, each listener fired a notification class, and each of the 2 notifications had a queue.
Once the first notification had
implements ShouldQueue
, the collection (with a join) I had passed to the listeners from the event gave theUndefined property: Illuminate\Contracts\Database\ModelIdentifier::$property
and so the second queue would never run. Removing theimplements ShouldQueue
makes it work.But since we need both notifications on the queue, what fixed it was removing SerializesModels from the event file. Now everything works with the queue as expected. Really not sure if this is a bug or what, since it works without the shouldQueue and only breaks with it!
You’re right, @themsaid I’ll try as soon as I have time to put a demo together 😉