In this step, we'll build the Model that will store our scheduled notifications:
Let's start by creating the migration for our Model:
php artisan make:migration create_scheduled_notifications_table
Migration
public function up(): void{ Schema::create('scheduled_notifications', function (Blueprint $table) { $table->id(); $table->foreignId('user_id')->constrained()->cascadeOnDelete(); $table->string('notification_class'); $table->morphs('notifiable'); $table->boolean('sent')->default(0); $table->boolean('processing')->default(0); $table->dateTime('scheduled_at'); $table->dateTime('sent_at')->nullable(); $table->integer('tries')->default(0); $table->timestamps(); });}
These fields include:
user_id
- the user that the notification is fornotification_class
- the class of the notification that will be sentnotifiable
- the Model that is associated with the notificationsent
- whether the notification has been sentprocessing
- whether the notification is currently being processed (for example, if a Job runs too long, we don't want to re-send)scheduled_at
- the date and time when the notification should be sent (in UTC time that matches Users timezone)sent_at
- the date and time when the notification was sent (Great for backlog and debugging!)tries
- the number of times the notification has been attempted to be sent (we'll limit it to 5 attempts)Next, we'll create the Model that will be used to interact with the database:
app/Models/ScheduledNotification.php
use App\Jobs\ProcessNotificationJob;use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Relations\BelongsTo;use Illuminate\Database\Eloquent\Relations\MorphTo; class ScheduledNotification extends Model{ protected $fillable = [ 'user_id', 'notification_class', 'notifiable_id', 'notifiable_type', 'sent', 'processing', 'scheduled_at', 'sent_at', 'tries', ]; protected $casts = [ 'sent' => 'boolean', 'processing' => 'boolean', ]; public function user(): BelongsTo { return $this->belongsTo(User::class); } public function notifiable(): MorphTo { return $this->morphTo(); }}
Last, we need some relationships to access all the scheduled notifications from the User and Booking Models.
To allow us to check if a user or a booking has scheduled notifications - we should add a relationship to the Models:
app/Models/User.php
// ... public function scheduledNotifications(): HasMany{ return $this->hasMany(ScheduledNotification::class);} // ...
app/Models/Booking.php
// ... public function scheduledNotifications(): MorphMany{ return $this->morphMany(ScheduledNotification::class, 'notifiable');} // ...
This way we will have the ability to list all upcoming/past notifications for our user or booking by just calling the $user->scheduledNotifications
or $booking->scheduledNotifications
relationship.