I'm creating a laravel website which has Messaging as an included feature.
I would like to take into consideration the following factors.
Both parties (the sender and the receiver) have the ability to delete the messages in their end.
if any of the parties deleted the message the other party should still having access to the message.
the message might have attachments.
I thought of the following schema but I think it has too much duplication and I'm looking for something better if any.
messages table:
-----------------
id
title
body
received_messages table:
------------------------
message_id
receiver_id
sender_id
is_read
sent_messages table:
------------------------
message_id
receiver_id
sender_id
Edit: Another schema came to my mind:
messages table:
-----------------
id
title
body
user_messages table:
-----------------
message_id
sender_id
receiver_id
sender_del // indicates that the sender deleted the message in their end
receiver_del // indicates that the receiver deleted the message in their end
read_at // timestamp null by default
When one party choose delete the message the corresponding field (sender_del, receiver_del) will be true so that the message will not be shown to that person
Using the previous schema the message will only be deleted from the DB if both parties deleted it
<?php
$user = auth()->user();
$received = $user->receivedMessages; // to get received messages
$sent = $user->sentMessages; // to get sent messages
any suggested modifications, which schema to use or a whole new schema are welcomed.
Thanks.
Just a question about what the best way is to send a message to a group (Like whatsapp group messaging).
I save the members per group into a separate database table and once a user sends a message to the group it retrieves the users from this table. I'm a bit stuck on part two:
As I see it there would be three methods.
Insert the message into a database for the entire group. Send the message back to the different users based on groups they are member of.
Insert the message in the database per user of the group. So loop the members and insert for every member. This has the advantage over the first method that downloaded, read and deleted status can be tracked.
Create a table for messages and one for the message-recipient link. But I'm not really sure how a would query in the most optimum way as to retrieve all the data (downloaded, read, etc) for a group of users. Is that possible in a single query?
Would anyone know what the best method would be? I can imagine that method 2 will fill up a database pretty fast, but method 1 doesn't have the ability of tracking status for a message.
At the moment I am using method 1, but I run into the problem that when a user deletes a message. It would still be returned on other devices because there would be no easy way of setting a certain deleted flag for group messages.
Does anyone know how apps like telegram, whatsapp and so on do this? And would method 2 give problems later on when millions of messages are sent?
Regards,
Ron
I would seperate it like this.
Messages
id, message, owner_id, deleted
Groups
id, name
Message_Group
message_id, group_id
User_Group
user_id, group_id
Then you can don't need to add a message to all users in that group. When you insert a new message you first inserts it into Messages, catch the id and inserts it into Message_Group with the message id and group id. To get the messages of a group just join Message_Group and Messages and you are pretty much done. Of course you also needs to join the user table to catch who wrote that messages.
I have have created a Private messaging system using PHP and mySQL with notification a bit like Facebook.
The database table has following fields( not all listed):
MessageID
senderUserID
RecUserID
Message
Subject
DateTime
Status - whether read or not
RepliedStatus - how should i use this?
DeleteRec - delete from inbox
DelSender - delete sender inbox
RepliedUserId - When user reply to orginal message this is change to receiver's id
All replies are stored in a second table, since each message create a thread. The second table looks a bit like this:
messageID - FK
repuserID
Mesage
DateTime
At the moment when a new message is sent out to a user i change the 'status' of the message to unread, From this can run a count query to list all of the unread messages in notification.
But if the users replies back to that message i cant set the original 'status' field to unread, since this will appear on both users notification. so i created another field called 'RepliedStatus ' but i am unsure how would i use this to show notification on message reply?
thanks guys.
If you have a replies table then you don't need a replied status column on your first status. By virtue of there existing a record in the replies table you know that a user has replied to a message
Why dont you add an INT and nullable column to the first table (let's say, "messages" table) named "previous_message"?
ALTER TABLE messages ADD COLUMN previous_message INT DEFAULT NULL;
So every message will have in the same table the previous one, and you can work out the sequence. If it helps you can have a "next_message" column with same definition and update the relevant record on reply.
Doing so you can use the status column on each reply.
If you want to keep the same DB organisation I would suggest to add a column status on the second table (let's say "replies").
Hope this helps
Me I'll put deleted column once and the same things for the read or not-read like:
[{"0":"both", "1":"Sender", "2":"receiver"}];
And then fetching a tread messaging like:
$sql = "SELECT * FROM messagetreads
WHERE (senderID OR receiverID = ".$_SESSION['MyCurrentId'].")
AND deleted !== 0
ORDER by TreadID AND DateTime ASC";
When a sender "delete" is tread... All tread relatedID in the database change for 1 or 0 if delete colomn is 2...
But I think it's better to creat another colomn for getting of the repeated deleted and notifications data like
TreadID (FK_message_Table)
delete (0=both deleted UserID=don't appear to this sender or receiver)
notify (0=both read UserID=read to this sender or receiver)
Then it's ezee to change a status or a delete statement.
The SELECT will be sometings like this:
$SQL = "SELECT *
FROM messagetreads
WHERE (senderID OR receiverID = ".$_SESSION['MyCurrentId'].")
IN (SELECT TreadID WHERE delete !== (0 OR ".$_SESSION['MyCurrentId']."))";
If is our member id involve in the colomn delete all the tread don't appear but if is the id of the receiver when the sender will delete 0 can be attributed so that both of the members can "delete" the message. Same thing for notifications!
very far later a cron-job can come delete very-old message read(0)...
PS: this can be notification system too like notifying for a new post in wall or comment on a photos or new events on calendar ... just add more information in column data and faormat it with php or java-ajaxed alike...
I am planning making a PM system for my users, overall it seems easy enough, but the way I have seen tutorials making PM systems, there is one problem.
In the way i planned it to work, there would be rows like, user_from, user_to and then the message - user_from would be the sender, and will see the message in his send messages, user_to will be the receiver and will see the message in his inbox. BUT, what if a user wants to delete a message from their sent folder, but the other user does not want to delete it from their inbox ??
Is there any simple way doing this ?
It could also be nice, to have the messages in conversations, like Gmail and Facebook, but that is maybe to hard to code (any tutorials appreciated)?
Use what's called a soft delete. This means when a record is 'deleted' it is never actually removed from the database but rather a flag is set to delete which allows you to remove it from a user interface while still having access to the data when you need it. So for this situation you could create two more columns called user_to_delete and user_from_delete. When either of these is set to true you would know not to show the message in the respective user's inbox/outbox. Goodluck.
You can fix the issue a few ways, but I would probably add a couple flags (from_deleted, to_deleted) to the table:
Instead of deleting the message, update the appropriate flag to 1.
When listing messages, filter out those that have been flagged.
You can setup the script so that after flagging, if both fields are flagged then you can actually delete the row.
I suggest the following database design:
MESSAGES
+----------+------------------+---------------------------+
| id | subject_id | body |
+----------+------------------+---------------------------+
SUBJECTS
+----------+-------------+--------------+-----------------+
| id | title | author | receivers |
+----------+-------------+--------------+-----------------+
INBOX
+----------+---------------+--------------+---------------+
| id | user_id | msg_id | read |
+----------+---------------+--------------+---------------+
OUTBOX
+----------+---------------+------------------------------+
| id | user_id | subject_id |
+----------+---------------+------------------------------+
When you send messages, you create a new row for all receivers in the inbox table, and in the outbox table one for the sender. In the messages table you insert one row with the ID of the subject and the message body. In the subjects table you insert one row with the title, author and all receivers (if the sender started a new subject or forwarded a full conversation or single message, otherwise add the message in the messages table using the existing subject ID) so that this info is kept even if one of the receivers deletes a messages from his/her inbox (in this case delete the row in the inbox table).
For the outbox there is no need for a 'read' flag, and notice that only the subject ID is used.
Another approach would be add two columns that will determine whether or not the owner or recipient have requested to delete (hide) the message.
owner_id | user_from | user_to | mailbox_folder | Message | Owner_hide | Recipient_hide
1 1 2 Sent Hi 1 0
Yes, there is a simple way of doing it! Having two more columns, respectively sender_deleted and receiver_deleted. If one of them "deletes" the message, then you updated the column with a value of 1. for example. When you display the messages, you select the messages you make sure the value is different than 1. Etc...
You would just create 2 rows, and add a column. example:
owner_id | user_from | user_to | mailbox_folder | Message
1 1 2 Sent Hi
2 1 2 Inbox Hi
Other columns: a unique row id, timestamps, subject line, etc...
Your mailboxes would then be built off of the owner_id column, and each user has their own copy to move/delete as they choose.
To add conversations, you could add a column, or another table. If it's a new message, get a new conversation id, otherwise use the same ID. Query by timestamps.
You could add a user_from_deleted & user_to_deleted rows and display a message only if it is not deleted.
To display the messages in conversations you could add an parent_id and display all the messages with the same parent_id
A PM system is a little more complex that one table. What if you PM more than one person?
In this case you would want multiple tables. One for users, messages, etc... You would link them up using primary and foreign keys.
Try looking up relational databases.
This should get you started:
http://www.databasejournal.com/sqletc/article.php/1469521/Introduction-to-Relational-Databases.htm
I am developing a messaging inbox system that uses a thread-based layout for messages. What I'm struggling with at the moment is updating the read status of the messages. Perhaps I have got the structure wrong so I could do with some guidance.
Here is what I have:
Table messages
==============
id
thread_id
from_user_id
subject
body
sent_date
Table message_threads
=====================
id
message_id
owner_id
member_id
owner_read
member_read
In the message_threads table, 'owner' refers to the user who started the thread, and 'member' refers to the other participant. A user's inbox will contain threads they have created themselves (owner), and also threads created by other users to which they have replied to (member).
The logic for setting the read status is as follows:
if owner sends a reply: 'member_read' field is set to 0 (unread), 'owner_read' field is set to 1 (read)
if member sends a reply: 'owner_read' field is set to 0 (unread), 'member_read' field is set to 1 (read)
Now I don't think this is entirely the correct approach, because suppose a member wants to sort messages in their inbox by read status - however a user can be both an owner and a member, and there are two read fields in the table. So this sort would not be correct.
Any suggestions on how I should go about this?
EDIT: Here is an exaple scenario:
User 1 sends Thread A to User 2
Thread A appears in User 2's inbox (status 0: unread)
User 2 opens Thread A
Thread A status set to 1 (read)
User 2 replies to Thread A
Thread A status in User 1's inbox (status 0: unread)
Thread A status in User 2's inbox (status 1: read)
User 1 opens Thread A
Thread A status set to 1 (read)
User 1 replies to Thread A
Thread A status in User 1's inbox (status 1: read)
Thread A status in User 2's inbox (status 0: unread)
The only "read" status is for messages that didn't originate from you. a reply to a recipient is marked read when opened. The sender doesn't care if it was read unless you want "receipt confirmation"
So - with that in mind here is what i think it should look like (i didn't include all fields in messages):
Table "users"
id
name
table "messages"
id (int)
parent_id (int)
from_user_id (id)
to_user_id
read (bit/bool)
message (text)
Let me know if I didn't understand you right.