I want to build a simple message system between my users of my website. For that i constructed table for messages as below:
tbl_messages
-pk id int
-fk sender_id int
-fk receiver_id int
-is_read boolean
-send_date datetime
When a user has my site opened in the browser and some other user sends him message, i want to send a notification message to the receiver user (something like 1 new message or (3)Messages) while the page of receiver is opened.
Eg: facebook notification, stackoverflow notification comes when new comment arrives
I performed such action by making a javascript function to be called every 2 min. This function makes an ajax request to output the notification. I wonder is this the correct and effective way to do because i have to perform the sql query every 2 min and if there are lots of records in my table, such action will create more load on database.
What other solutions can I perform instead of this?
If you correctly indexed your database and designed your program, it shouldn't be a problem.
You won't be able to design a notification system as responsive as Facebook and other, since it's almost impossible to create push systems with PHP.
If you have a dedicated/virtualized server (and not shared hosting), look into things such as NodeJS.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm working on a college project where I have to made a chat that contains invitation options with ACCEPT/REJECT between registered users only. If an invitation is accepted, then open the chat otherwise send a message to the sender.
I've completed the whole project except this invitation option. I know that I can use COOKIE for this (with setInterval), but I need something more secure idea to do this.
In my current PHP invite function, (for example: invitation sender: a#a.com, invitation for: b#b.com) I used to verify the b#b.com user (registered or not) and send back the JSON with verification. If user is registered, then open a chatbox on self-end only (a#a.com) and can send message to b#b.com. The b#b.com user will only gets these message when it opens the chatbox with invitation sender : b#b.com, for: a#a.com.
I have no idea to how to send an invitation directly to b#b.com with option and get back the clicked event (accept/reject) to `a#a.com.
Currently there is a single idea in my mind: cookie with setInterval. But there is a demerit of this idea is, both users page continuously checks the cookie, it means more load on bandwidth and more process on user-end and most of all, it's not secure.
And I'm already user 3 setInterval functions into my project : status check, new msgs check and chat options.
So, can anybody suggest a better approach?
This is rather a broad question, but I'll try to offer some basic design guidance. I expect that a user will enter their email address and the email address of the other person, and click on a "log on" button.
What happens next depends on your design, but this is what I would do. This involves AJAX operations, which is fine for the purpose.
The details are submitted to the server, and a row in a user table is created. The user gets an ordinary session cookie by default, so you just need session_start at the start of each page. A row in a conversations table is also created.
We'll assume that the user is now in a connected but not chatting state.
Using jQuery or similar, a call is made periodically to the server to see if the application status from their side needs updating. To start with, this will determine whether the other user is available. Let's say this call is made every 10 seconds, to avoid excessive load, and every time a call is made, the user table is updated with a last_seen_at timestamp.
You run a script on your server that examines live conversation rows and sees if both parties are online. If they are, and the conversation is not marked as started, then update the row and then notify the users when they next request an update.
When your browser application receives a notification of some kind (in the reply to a periodic AJAX request) it will need to redraw its screen. The life-cycle is: start -> log-on -> waiting -> chat -> log-off. You'll need to work on the JavaScript to do this.
Some of the fields in my suggested table structure below are used to capture the state of the chat, so your PHP application doesn't have to remember things itself. For example if conversation.accepted_by_user_id is null, the conversation is waiting for the second user to accept the chat request. If message.received_at is populated but message.sent_at is null, it means the message needs to be transmitted to the second user when they next send an update request.
Where users or conversations get too old, they can either be marked as stale or deleted entirely.
Side note: we have made no attempt to check that the users own the email addresses they have specified, or whether they even exist. But, for the most part, it doesn't matter - all we need is for the two parties to have a unique string that they can both remember.
Suggested tables:
user (
id (pk) int,
email varchar, // user's email address
email_to varchar, // the email address of who they wish to chat to
session_id varchar,
last_seen_at timestamp
)
conversation (
id (pk) int,
started_by_user_id int, // foreign key
accepted_by_user_id int, // foreign key (null if not yet accepted)
from_notified_at timestamp,
to_notified_at timestamp // timestamp (null if not yet accepted)
)
message (
id (pk),
conversation_id int, // foreign key
is_forward boolean, // true = a->b, false = b->a
message_text varchar, // actual text of message
received_at timestamp, // when it was sent in a server message
sent_at timestamp // when it was picked up in a server message
)
You were worried about the security of cookies. If you use session cookies it means that only the user that initiates a session can use the session ID given to it by PHP (there are a couple of exceptions: the theft of a cookie by a malicious third party via script injection or the capture of data by eavesdropping. You can use SSL and read up on XSS if you are worried about those things, but I would say it is beyond the scope of a college course).
Long story short, you've chosen a non-trivial project! Good luck with it, and if there is something you don't understand, break it down into a smaller pieces, until the pieces are each programming problems.
Now, you can do this project with sockets, but you should learn to walk before you start running. I would suggest you try it this way first (since it is easier but still hard enough) and then if you can do that, move on to sockets.
I want build a notification system to my website, similar to Facebook. The notifications don't need to be in real time.
This is what I have in mind:
User create an event (upload a new photo, add a new comment, like a photo, or even an administration alert to all users)
Run a cronjob every 5 minutes to add the notifications into the notifications table: id|id_content|type_of_content_enum|affected_user_id|date|seen_bool
The cronjob, will run several functions for each type of notification, for example:
add_photos_notification() // This function will check all photos added in the past 5 minutes, and insert a row in the notification table, for each user following this person. The function will group all photos added into the past 5 minutes, so the follower don't get many notifications for the same type of content. Resulting in a notification like: User X added Y photos in his profile.
add_admin_notification() // This function will check all news added by the administration of the site in the past 5 minutes, and insert a row in the notification table, for each user on the system ...
Is this a correct approach to build a notification system?
Is it possible to miss an event, running a cron every 5 minutes where functions retrieve the past 5 minutes events?
To be safe, do you think an alternative could be checking all events where a field 'notified' is not true? The same function that will grab the events where 'notified' = false, update it to true after adding that notification into the notifications table.
Thanks,
I went with the cronjob route and working good so far. Since our system got so many users to be notified, I found it the most appropriate way to do for two reasons.
I don't need to edit my current scripts code, inserting functions to add notifications for every event I want notify.
Since there gonna be some actions where many users are affected, adding notifications in real time could result in long script delays and time outs.
I built a class called notifications and inside this class, there are functions to add notification for every event I want notify, for example: user_added_a_new_photo(); user_commented_on_a_photo();
For every notification generate, Im adding 1 entry per user to be notified. This is how my notifications db looks like:
id
affected_user_id //user being notified
user_generating_the_notification_id
content_type // enum containing all type of notifications my system has (example: photo, video, comment) ...
content_json // a json containing the notification content. Based on the content type, on the display view file, I call helpers that will format the notification row using the json info.
date // the date the notification was added
seen_on // the date the user saw the notification
clicked_on // if user clicked on the notification, store the date he clicked on it
display // true or false
For this purpose, I added the display field cause for every new notification I create, I check the database if the same user, has another not seen notification, from the same generating user. If this condition is true, I set the old notification to display = false, and group the two new notifications resulting in something like: User X added X new photos in his gallery.
The clicked_on field, stores the date the item was clicked so I can generate reports based on this info if I need to. When displaying the content, if this item is not null, I highlight the notification to mark those not checked yet.
I created a text field to store the notification content in json, cause different notifications has different styles to present the users. For example, a new comment notification, has only texts, but a new photo notification, has a preview thumb.
So far, no issue running it and working for my needs.
The only downside, since the cronjobs can only be run only every 1 minute, the notifications may have 1 minute delay. But since I don't need it in real time, I set the cronjob to run every 5 minutes.
I've been looking into something like this as well and i just found this question on stackoverflow
Building a notification system
Have a look at the answer, the user does shed a fair bit of light on the theory of how to implement this sort of system.
As far as i can see you would need to create a record or object for each notification, if 100 people are subscribe to that event then 100 records will be generated. When a page is loaded your system will find all the notifications that correspond to the user logged in (Maybe by record ID) and then you would notify the user of how many notifications they have.
Now another way of doing this (Note i haven't implemented any of these, they are just ideas) would be to make a notification in a a table, then we'd have a second table that will hold a users ID and a notification ID, a user will be added to this table when they are subscribed to a notification, for example, confirmation of a friend request.
Please note again, these aren't proven methods, they're a result of some of my research of the matter, i'd read the post i gave you before doing anything.
If you have ever been to a sms messaging site, you probably have seen that users can decide they want to schedule the sending of their sms message at a later time.
So a user logs on to the site (a real life example is at http://www.smslive247.com or http://routesms.com), composes the sms and clicks on "send message at a later time" radiobox. This gives users a datetime field that you can then pick what date and time you want the message to be dispatched (as well as ability to change the timezone).
Basically, users can schedule the sending of sms.
I'm also designing a similar site and wondering if anyone can tell me how this is done.
Thanks.
Use a message queue, for example in a database, that gets read by a separate process (a service, or cron job for example) that processes the records and sends the message.
One approach is to store the message and write a service to send queued messages. You can store the messages in a database.
One approach is to use a database.
Create a table with a column that contains the datetime the message should be sent, and another column with the message.
From a background thread (or even another process, such as a Windows Service or a SQL Agent task), wake up every once in a while, read the top row in the table, and see if it's time to execute it. Something like:
CREATE TABLE MyQueue (
TimeToExec DATETIME NOT NULL,
Message NVARCHAR(MAX) NOT NULL
)
INSERT INTO MyQueue VALUES(GETDATE(), N'message')
;WITH MYCTE AS (
SELECT TOP 1 Message
FROM MyQueue
WITH (ROWLOCK, READPAST)
WHERE TimeToExec <= GETDATE()
ORDER BY TimeToExec
) DELETE FROM MYCTE
OUTPUT DELETED.Message
I have a question for anyone with experience in dealing with complex coding in PHP, Jquery and SQL. I realize I wrote a lot but I wanted to be detailed. I have an issue with 1 solution that I can think of but it doesn't seem very efficient, especially with large amounts of traffic. I have a table that stores messages from users. I am designing a chat platform where users can open a chatbox and send instant messages to other users who are their friends.
I need the ability to have it so when a user opens a box from his online friends and sends a message, that friend will have a chatbox pop up with the message or messages and the box will update from there. I would like that box to also maintain the previously sent messages in it from page to page when the user is navigating the site until he closes the box. When this happens, I created a viewed column which I can mark as 1 for all the messages that were in that box at the time. From then on those messages will not pop up. Only new ones will. So closing the box essentially resets it.
I have a simple JSON function where information is sent and a php handler runs a query and returns all the messages. They are then sorted into their boxes.
What I think is one solution is to put a refresh time interval on the json code and check for messages constantly where viewed=0. If there are and the box has not yet popped up, it will and have the messages html'd into the boxes. The problem with this is that the query will be selecting all the messages that the user has received and they will be constantly overwriting the boxes which won't show visually but seems taxing on the system. I was trying to think of a way that involves a query that checks for timestamps that are greater then a timestamp sent in the jquery function. IF anyone has any recommendations or useful articles or information, I would greatly appreciate it.
$.getJSON("../collabrr/chatbox.php?action=view&load=initial&receiver="+username+ "&token="+ token, function(json) {
for(i=0; i < json.length; i++) {
openchat({ data : { user : json[i].user }}); //makes chatbox open up with name of sender
$('#chatbox[data-name="'+json[i].user+'"]>#messagebox').prepend('<div id="chatbox-response">'+json[i].user+':'+json[i].message+'</div>').find('li').fadeIn(1500);
}
});
$sql = 'SELECT timestamp, user, message, receiver
FROM chatbox WHERE receiver=? AND viewed=? ORDER BY timestamp DESC';
$stmt = $conn->prepare($sql);
$result=$stmt->execute(array($_GET['receiver'],0));
}
Field Type Null Key Default Extra
id int(6) NO PRI NULL auto_increment
convo_id varchar(35) NO NULL
timestamp int(11) NO NULL
user varchar(25) NO NULL
receiver varchar(25) NO NULL
message varchar(150) NO NULL
viewed int(1) NO NULL
Polling the server for updates is one solution. I can give you another one, however I dont know if you have the resources availabe/the time to implement it.
In very short, this is what I did when I implemented something similiar: the basic idea is to use Websockets and keep a socket open to a backend. Preferably node.js using socket.io because of its non blocking nature. Then you would use redis and its pub/sub capabilities to receive updates from client A and push them to client B.
When client A loads your website, it connects via a Websocket to a running node.js process, call it PUBLISHER. Publisher subscribes itself to a specific channel in redis for this client. Client B loads your website, it also connects to Publisher etc. just like client A. Now client A writes something and it is sent to Publisher. Publisher publishes this event to its redis channel. Client B gets noticed, because he is not only subscribed to his channel, but also to A´s channel (maybe because they are friens on your social network site if you have one).
This sounds probably rather complicated, and it is not that easy to implement, but maybe this can give you a basic idea about how such a pub/sub system is implemented. Polling should only act as a fallback solution because on a high traffic website constantly polling your webserver with ajax requests every 100ms or so will cause extreme load.
It sounds like what you're wanting is an Ajax push solution (also known as 'Comet' for some unknown reason).
Here is a site which explains how to do it in PHP/Javascript: http://www.zeitoun.net/articles/comet_and_php/start
See also the wikipedia page: http://en.wikipedia.org/wiki/Comet_%28programming%29
(heh, I note that also includes an explanation of the name 'Comet')
How can I show users that they have a new message or response awaiting in their inbox by showing them a number or text telling them to check it and then only remove the notification automatically if the user responds to it or clicks "done" (meaning no further response necessary).
I assume the messages will be stored in a DB. Just add a 'read' boolean column and then query the DB for unread messages to know whether there are new messages.
When the user replies you set the read column to 1.
This really needs javascript. Basically you have javascript make a request every x amount of seconds to a php page that checks for new notifications. Then the javascript alerts the user.
if you wan't something like on facebook, and other social network sites, U need to use javascript to do this. Php is serverside language, and that can;t do.
if you don't ask that, and u are only interested how to solve this with php and database.
Try to make new row. Called status, and update table set that coloumn is 1 if is read, 0 if isn't read...