Handling delayed notifications in Laravel (Updated)

Adam Campbell
3 min readSep 18, 2017

--

Note: This is v2. My original post was updated on 2/19/18 to include omitted parts of this flow, like using events, to better control delayed notifications.

Sending notifications in your Laravel app has never been easier, thanks to the built-in Notifications functionality. Notifications can be sent over almost any channel you can think of — in-app, email, SMS, push, phone, chat apps, etc — are queuable, templatable, and super simple to use.

Many notifications are sent in the moment: when an action happens, when a state changes, or when some other event is triggered, and when you know the exact conditions of whether or not the notification should be sent. But what about when you need to send notifications outside of that moment, like 5 minutes or 2 hours or 3 days before or after an action or event? And, more importantly, what if the situation can change between the action and the time you need to send the notification?

By using a combination of the delay()and via() methods, plus events, it’s possible to elegantly handle conditional notifications.

The Setup

Let’s say we have a notification that should be sent 24 hours before an appointment. The notification may look something like this:

The delay() method allows us to queue up the notification but hold off sending it until whenever we prefer the notification can be dispatched immediately. Regardless of when the user books the appointment, the notification can be scheduled to not send until, say, exactly one day before the appointment.

$user->notify(new AppointmentReminder($appointment));

The Sanity Check

The via() method is called at the moment the notification is to be queued to determine the channels to use for notification. This method can use our own business logic to be smart and check if the notification should be queued at all. In this example, we’re encapsulating that logic in a secondary public dontSend() method. This is important.

Let’s update our notification.

If the check fails then via() returns an empty array of notification channels and nothing is sent.

Ok, all good so far. If the appointment has been cancelled by the time we queue the notification then it won’t be sent. This is fine, but not as useful as it could be. It’s unlikely the appointment would be cancelled the moment after it was booked.

What happens if the user booked the appointment weeks ahead of time, but has since cancelled? The day-before notification shouldn’t be sent, but we’re not able to easily pull it out of the queue. This is where Events come in.

The Goods

Whenever a notification is being handled in Laravel the NotificationSending event is first emitted. We can use this event to once again check if the notification should be sent, thanks to SerializesModels and our dontSend method.

Check out the following set of classes:

By listening to that event and then checking our dontSend() method on our notification, we can do in-the-moment checks as the notification is being handled to see if it’s still valid. You can even access the $notifiable object, which allows you to check fresh data about the user or entity you’re notifying.

As you can see, handling conditional queued notifications can be a breeze! Notify your users whenever you like, and feel confident that your notifications will never send when they no longer apply.

--

--

Adam Campbell

Canadian in Alabama. Husband, father, designer, developer, learner. CTO at @spurjobs.