DatabaseProvider
The DatabaseProvider
stores notifications in a table that you can then query to show in your application. It also provides a DatabaseNotificationService
to interact with the notifications for a Notifiable
including pagination and marking as read.
Requirements
To use the DatabaseProvider
, you need a table to store the notifications in. A migration is provided in Megaphone that you can copy to your application to use. If you are not using cfmigrations
, create a table that has the same structure in your database. The table name can be customized, if needed.
component {
function up( schema ) {
schema.create( "megaphone_notifications", ( t ) => {
t.guid( "id" ).primaryKey();
t.string( "type" ); // notification wirebox id
t.string( "notifiableId" );
t.string( "notifiableType" );
t.longText( "data" ); // serializeJSON of what is returned from `toDatabase`
t.timestamp( "readDate" ).nullable();
t.timestamp( "createdDate" ).withCurrent();
t.index( "type" );
t.index( "readDate" );
t.index( name = "idx_megaphone_notifications_notifiable_index", columns = [ "notifiableId", "notifiableType" ] );
} );
}
function down( schema ) {
schema.dropIfExists( "megaphone_notifications" );
}
}
Configuration
The DatabaseProvider
accepts the following properties:
{
"tableName": "megaphone_notifications",
"datasource": null,
"queryOptions": {}
}
These can be different for each channel you configure using the DatabaseProvider
.
moduleSettings = {
"megaphone": {
"channels": {
"db1": {
"provider": "DatabaseProvider@megaphone",
"properties": { "datasource": "db1" }
},
"db2": {
"provider": "DatabaseProvider@megaphone",
"properties": { "datasource": "db2" }
}
}
}
};
The datasource
property will override any datasource
property on the passed-in queryOptions
.
toDatabase
The toDatabase
method returns a struct
of data to save as the body of the notification in the database. This data will be available when reading the notifications back from the database later.
public struct function toDatabase( required any notifiable ) {
return {
"stockSymbol": getStockSymbol(),
"completionTimestamp": getCompletionTimestamp()
};
}
Interacting with Database Notifications
Where most Megaphone Providers opearte as fire-and-forget, the notifications sent by the DatabaseProvider
need to be shown in your application to be of any use. The DatabaseProvider
provides a few extra components to help you do this.
Just like sending notifications, there are two ways to retrieve notifications sent through the DatabaseProvider
: using the DatabaseNotificationService
and using the HasDatabaseNotifications
delegate. These two options return the same results, so use whichever one you prefer.
DatabaseNotificationService
The DatabaseNotificationService
can be injected into any component in your application to retrieve DatabaseNotification
instances for a Notifiable
.
component {
property
name="databaseNotificationService"
inject="DatabaseNotificationService@megaphone";
function index( event, rc, prc ) {
// ...
var cursor = variables.databaseNotificationService.getUnreadNotifications(
notifiable = auth().user(),
channel = "database" // default is "database",
initialPage = 1 // default is 1,
maxRows = 25 // default is 25
);
// ...
}
}
This will return a DatabaseNotificationCursor
paging over all unread notifications for the passed in Notifiable
.
HasDatabaseNotifications
The HasDatabaseNotifications
delegate allows you to get the notifications directly from a Notifiable
instance.
component name="User" delegates="HasDatabaseNotifications@megaphone" accessors="true" {
property name="id";
public string function getNotifiableId() {
return getId();
}
public string function getNotifiableType() {
return "User";
}
}
component {
function index( event, rc, prc ) {
// ...
var cursor = auth().user().getUnreadNotifications(
channel = "database" // default is "database",
initialPage = 1 // default is 1,
maxRows = 25 // default is 25
);
// if you want all the defaults:
var cursor = auth().user().getUnreadNotifications();
// ...
}
}
DatabaseNotificationCursor
The DatabaseNotificationCursor
provides a way to paginate through the notifications while also being able to either markAllAsRead
or deleteAll
of the notifications contained in the cursor.
cursor.getPagination(); // { "maxRows": 25, "totalPages": 1, "offset": 0, "page": 1, "totalRecords": 5 }
cursor.getResults(); // [ DatabaseNotification ]
for ( var notification in cursor.getResults() ) {
notification.getMemento(); // { id, type, notifiableType, notifiableId, data, readDate, createdDate }
notification.getData(); // struct / already deserialized
notification.getType(); // string — notification wirebox id
notification.markAsRead( readDate = now() ); // sets and saves the readDate, default = now()
notification.delete(); // deletes the notification from the database
}
cursor.hasPrevious(); // boolean
cursor.previous(); // loads previous page from database
cursor.hasNext(); // boolean
cursor.next(); // loads next page from database
cursor.markAllAsRead( readDate = now() ); // marks all as read, not just current page. default = now()
cursor.deleteAll(); // deletes all, not just current page
DatabaseNotification
The component returned as the notification inside the DatabaseNotificationCursor
is an instance of DatabaseNotification
. This allows you to retrieve the data you sent as well as interact with the DatabaseNotification
by checking the sending Notification
type, marking the DatabaseNotification
as read or deleting the DatabaseNotification
.
notification.getMemento(); // { id, type, notifiableType, notifiableId, data, readDate, createdDate }
notification.getData(); // struct / already deserialized
notification.getType(); // string — notification wirebox id
notification.markAsRead( readDate = now() ); // sets and saves the readDate, default = now()
notification.delete(); // deletes the notification from the database
Last updated