In Laravel, crafting notification classes can often feel repetitive (and WET), especially in projects that rely heavily on notifications. Meet Raven – the solution that simplifies the process of sending notifications through multiple channels in Laravel, allowing you to focus on your peculiar business logic. Currently, Raven seamlessly handles email notifications through SendGrid and Amazon SES, as well as database/in-app notifications. Stay tuned, as support for SMS notifications will be integrated in the near future.
To use this package, you need the following requirements:
You can install this package via Composer using the command:
composer require chijioke-ibekwe/raven
Next, you will need to publish and run the migration files, and the config file. The following command will allow you do all of the above:
php artisan raven:install
The migrations will be published in your project's migrations directory ./database/migrations
while the config file
raven.php
, will be published in your config directory ./config
. Content of the config file is as shown below:
<?php
return [
'default' => [
'email' => env('EMAIL_NOTIFICATION_PROVIDER', 'sendgrid'),
'sms' => env('SMS_NOTIFICATION_PROVIDER', 'vonage')
],
'providers' => [
'sendgrid' => [
'key' => env('SENDGRID_API_KEY')
],
'ses' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'template_source' => env('AWS_SES_TEMPLATE_SOURCE', 'sendgrid')
]
],
'customizations' => [
'mail' => [
'from' => [
'address' => env('MAIL_FROM_ADDRESS', '[email protected]'),
'name' => env('MAIL_FROM_NAME', 'Example'),
]
],
'queue_name' => env('RAVEN_QUEUE_NAME')
'templates_directory' => env('TEMPLATES_DIRECTORY', resource_path('templates'))
],
'api' => [
'prefix' => 'api/v1',
'middleware' => 'api'
]
];
default
array allows you to configure your default service providers for your notification channels. Optionssendgrid
and ses
. (vonage
for SMS will be integrated soon).providers
array is where you supply the credentials for the service provider you choose. When using ses
, yousendgrid
. If this is your preferred option, the templates_source
should besendgrid
. NB: For this to work, you need to also provide your credentials for the sendgrid
provider.templates_source
infilesystem
and the directory of the templates should be provided on the templates_directory
under customizations
. (This option is not currently supported for emails, but will be in the near future).customizations
array allows you to customize your email parameters, optionally your queue_name
(nottemplates
in the resources pathemail
(relevant only if your template source is filesystem
and provider is ses
), sms
, and in_app
.email
directory will contain the .html
templates for your emails.sms
directory will contain the .txt
files with the contents of your sms notifications.in_app
directory will contain .json
files whose contents will be saved on the data column of the database notifications table.{{name}}
.email_template_filename
, sms_template_filename
and in_app_template_filename
columns on the notification context record.api
array allows you to customize the provided API routes with prefix and middleware group.After the migrations have been run successfully, you can then proceed to add notification contexts to the database. To do this, simply create and run migration files similar to the ones below:
sendgrid
as provider or template source)<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$id = DB::table('notification_contexts')->insertGetId(
array(
'name' => 'user-verified',
'email_template_id' => 'd-ad34ghAwe3mQRvb29',
'description' => 'Notification to inform a user that they have been verified on the platform'
)
);
DB::table('notification_channel_notification_context')->insert(
array(
'notification_channel_id' => 1, //EMAIL
'notification_context_id' => $id
)
);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
DB::table('notification_contexts')->where('name', 'user-verified')->delete();
}
};
ses
as provider and filesystem
as template source)<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$id = DB::table('notification_contexts')->insertGetId(
array(
'name' => 'user-verified',
'email_template_filename' => 'user-verified.html',
'description' => 'Notification to inform a user that they have been verified on the platform'
)
);
DB::table('notification_channel_notification_context')->insert(
array(
'notification_channel_id' => 1, //EMAIL
'notification_context_id' => $id
)
);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
DB::table('notification_contexts')->where('name', 'user-verified')->delete();
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$id = DB::table('notification_contexts')->insertGetId(
array(
'name' => 'user-verified',
'description' => 'Notification to inform a user that they have been verified on the platform',
'in_app_template_filename' => 'user-verified.json',
'type' => 'user'
)
);
DB::table('notification_channel_notification_context')->insert(
array(
'notification_channel_id' => 2, //DATABASE
'notification_context_id' => $id
)
);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
DB::table('notification_contexts')->where('name', 'user-verified')->delete();
}
};
user-verified.json
{
"title": "You have been verified",
"body": "Hello {{name}}. This is to let you know that your account with email {{email}} has been verified",
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$id = DB::table('notification_contexts')->insertGetId(
array(
'name' => 'user-verified',
'email_template_id' => 'd-ad34ghAwe3mQRvb29',
'description' => 'Notification to inform a user that they have been verified on the platform',
'in_app_template_filename' => 'user-verified.json',
'type' => 'user'
)
);
DB::table('notification_channel_notification_context')->insert(
array(
array(
'notification_channel_id' => 1, //EMAIL
'notification_context_id' => $id,
),
array(
'notification_channel_id' => 2, //DATABASE
'notification_context_id' => $id,
)
)
);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
DB::table('notification_contexts')->where('name', 'user-verified')->delete();
}
};
To send a notification at any point in your code, build a Scroll
object, set the relevant
fields as shown below, and dispatch a Raven
with the Scroll
:
$verified_user = User::find(1);
$document_url = "https://example.com/laravel-cheatsheet.pdf";
$scroll = new Scroll();
$scroll->setContextName('user-verified');
$scroll->setRecipients([$verified_user, '[email protected]']);
$scroll->setCcs(['[email protected]' => 'John Doe', '[email protected]' => 'Jane Doe']);
$scroll->setParams([
'id' => $verified_user->id,
'name' => $verified_user->name,
'email' => $verified_user->email
]);
$scroll->setAttachmentUrls($document_url);
Raven::dispatch($scroll);
contextName
property is required and must match the notification context name for that notificationrecipients
property is required and takes any single notifiable/email string, or an array of notifiables/emailccs
property is exclusively for email notifications and takes an array (or associative array with email/name asparams
property is an associative array of all the variables that exist on the notificationattachmentUrls
field takes a url or an array of urls that point to the publicly accessible resource(s) thatTo successfully send Database Notifications, it is assumed that the user of this package has already set up a notifications table in their project via the command below:
php artisan notifications:table
And subsequently:
php artisan migrate
The data column for database notifications using this package, will capture whatever key-value pairs you have in the json template for that notification.
All placeholders surrounded by {{}}
in the template will be replaced with their values passed in as params of the same name when creating the Scroll
object.
The package takes care of the rest of the logic.
The following API is included in this package for ease of use:
GET /api/v1/notification-contexts
{
"status": true,
"msg": "Success",
"data": [
{
"id": 1,
"email_template_id": "d-ad34ghAwe3mQRvb29",
"email_template_filename": null,
"name": "user-verified",
"description": "Notification to inform a user that they have been verified on the platform",
"sms_template_filename": null,
"in_app_template_filename": "user-verified.json",
"type": "user",
"active": true,
"notification_channels": [
{
"id": 1,
"type": "EMAIL"
}
]
}
]
}
401
response:{
"status": false,
"message": "You are not authorized to access this API"
}
The following exceptions can be thrown by the package for the scenarios outlined below:
RavenEntityNotFoundException
code: 404
Scroll
object that has a contextName
which does not exist on the database.RavenInvalidDataException
code: 422
Scroll
object without a contextName
or recipient
.NotificationContext
that has no email_template_id
when your email provider orsendgrid
.NotificationContext
that has no email_template_filename
when your emailses
and template source is filesystem
.NotificationContext
that has no in_app_template_filename
.NotificationContext
that has a non-existent template file that matches thein_app_template_filename
in the in-app template directory.email
field or a routeNotificationForMail()