How Laravel's SerializesModels Trait Could Save Your Baconby JacobBennett
When a Laravel Job is dispatched that takes an Eloquent Model as an argument in the constructor, you can use the
SerializesModels trait which will only serialize the model identifier. When the job is actually handled, the queue system will automatically re-retrieve the full model instance from the database (docs). Taylor also announced that in Laravel 5.3, you will also be able to do this with Eloquent Collections! (link)
So why is it necessary or helpful for the framework to re-retrieve the model values from the DB at run time instead of just serializing the attributes of the given model or collection? Let's use a contrived example to demonstrate.
Let's say that you create a new job called
SendWelcomeEmail that will be dispatched from your
RegistrationController each time a new user signs up for your application. Ideally we don't want our user to have to wait for the welcome email to be sent when they sign up, so we make our
SendWelcomeEmail job push onto the queue instead. To accomplish this, Laravel magic only requires that our job
ShouldQueue interface. Great!
Here is where the paths diverge.
Scenario 1: We already have the email address of our user and we pass through the users email to the job's constructor. Something like
$user = User::find(1); dispatch(new SendWelcomeEmail($user->email));
Scenario 2: We decide to pass the entire User model into our constructor and use the
SerializesModels trait in our
SendWelcomeEmail job. Something like
$user = User::find(1); dispatch(new SendWelcomeEmail($user));
The difference in implementation is nearly indistinguishable, but let's play devils advocate for a minute and see how this might play out.
In Scenario 1, a user signs up, and our job is queued to run. Your application was featured on product hunt this morning however, and you have 100s of emails waiting to be sent in your queue. Your user upon signing up realizes they mistyped their email address, and promptly corrects it in the settings of your app. By the time your queue gets around to the
SendWelcomeEmail for this user, the email that was serialized with the job is no longer valid. The user never gets their welcome email and the world stops spinning.
In Scenario 2, all the same steps take place, but when the queued
SendWelcomeEmail job finally gets its turn to run, Laravel pulls the latest info for the passed in
User, and the email gets sent to the updated email address! Praise be to you almighty dev.
To learn more about Laravel Jobs and utilizing the Queue, check out the amazing Laravel Docs on Queues
I tried to comment here, https://gistlog.co/JacobBennett/e60d6a932db98985f160146b09455988, even though I was already logged in on Github. But it didn't allow me. :(
@davecarlson This would be a good problem to have!
Hi Jacob, I read your article. Its great. I am still not very clear about how to use queues when it comes to passing database instances / models. I keep on getting errors "Type error: Too few arguments to function". Could you please help answer my query on SO?
Hi Jacob also in the real life scenario when a user is registered we send them confirmation mail to confirm their address and just after that we consider them for truly registered and just after that we can send them Welcome mail. Beside this your article is cool and useful for other use-cases as: app notifications, newsletter subscriptions, marketing campaigns :) and so one. So GJ