I see no-one here addresses the fact, that notifications are usually re-occurring, aka. notification of an upcoming transaction is always going to be the same, but with a different transaction ID or Date in it. as so: { You have a new upcoming payment: @paymentID, with a due date of @dueDate }.
Having texts in a different table can also help with
- If you want to change the notification text later on
- Making the app multilingual is easier, because I can just layer the notifications table with a language code and retrieve the appropriate string
Thus I also made a table for those abstract notifications, which are just linked under the the user with a middle table, where one notification type can be sent to one user at multiple times. I also linked the notifications to the user not by a foreign key ID, but I made notification codes for all notifications and full_text indexed the varchar field of those codes, for faster read speeds. Due to the fact that these notifications need to be sent at specific times, it is also easier for the developer to write
NotificationService::sendNew( Notification::NOTE_NEW_PAYMENT, ['paymentId'] => 123, ['dueDate'] => Carbon::now(), 'userIdToSendTo' );
Now since my messages are going to have custom data in them, that is inserted into the string, as you can see from the second argument beforehand, then I will store them in a database blob. as such
$values = base64_encode(serialize($valuesInTextArray));
This is because I want to decouple the notifications from other tables and as such I dont want to crete unnessecary FK relations from and to the notifications table, so that I can for example say notification 234 is attached to transaction 23 and then join and get that transaction ID. Decoupling this takes away the overhead of managing these relations. The downside is, it is nigh impossible to delete notifications, when for example a transaction is deleted, but in my use case I decided, this is not needed anyway.
I will retrieve and fill the texts on the App side as follows. Ps. I am using someones vksprintf function (https://github.com/washingtonpost/datawrapper/blob/master/lib/utils/vksprintf.php), props to him!
$valuesToFillInString = unserialize(base64_decode($notification->values));
vksprintf( $notificationText->text, $valuesToFillInString )
Notice also which fields I index, because I am going to find or sort by them
My Database design is as follows
==============================
TABLE: Users
==============================
TABLE: Notifications
- id (pk)
- user_id (fk, indexed)
- text_id (fk - NotificationTexts table)
- values (blob) [containing the array of values, to input into the text string]
- createdDateTime (DateTime)
- read (boolean)
[ClusterIndex] => (user_id, createdDateTime)
==============================
TABLE: NotificationTexts
- id (pk)
- text_id (uniquem indexed)
- text (varchar) [{ You have a new upcoming payment: @paymentID, with a due date of @dueDate }]
- note (varchar, nullable) [notes for developers, informational column]