I want to learn how to make one of these systems from scratch and I'm find a lot of junk links on Google. I really just want a simple tutorial for the most basic PHP and MySQL chat so I can understand the concept before I start messing with jQuery/AJAX.
PHP/MySQL chat 101:
1) user opens a browser
2) user enters address in brower
3) browser sends HTTP request
4) server recieves HTTP request
5) server tells PHP interpreter to run PHP script
6) PHP script connects to MySQL database
7) PHP script retrieves list of messages
8) PHP generates HTTP response made of HTML code with messages and form
9) Server sends HTTP response to browser
10) Browser draws HTML from HTTP response
11) User types new message and submits the form
12) Browser send HTTP POST request
13) ...
A very simple starting point
Have a database table for a Message
id | user | timestamp | message
And have a PHP page that sends an AJAX request to read any new messages.
This will involve checking the database to see if there are any messages since the time the request was received. If no messages, then loop, wait and try again in 100ms (or whatever you think is acceptable lag).
When the Ajax request returns a message (a JSON response would be best), output the user, time and message to the page using JQuery.
The live part of your chat is the tricky part, if you are just beginning i would skip that.
Start by building a simple guestbook, and then add more features.
There are many tutorials available on how to build a guestbook, and even some free scripts where you can learn from.
After you got your guestbook working, you could add features like auto-loading new messages to make it appear as live, using AJAX polling. What you basically do make an AJAX call to the server at a regular interval to get all the messages and display it on your page.
Found very interesting tutorial here
http://tutorialzine.com/2010/10/ajax-web-chat-php-mysql/
If you must use php and mySQL for chat, atleast have a seperate table for unread messages. If you poll you will most likely need to check the database for new messages every 100ms or so. If your total message table is 1000 rows checking every 100ms will kill your server (especially if many users are connected). I would structure my mySQL database with a table for only unread messages and move them to a bigger table for old messages once read. That way your not checking a big table all the time.
Even better is to use a cache database for unread messages like redis (facebook used memcacheD).
Even even better is to just not use php all together and use an event driven language with callbacks like node.js
Related
I've implemented realtime chat in Websockets and it works just like a charm. I did it side by side with AJAX polling (which existed before), as I didn't want to remove AJAX polling support for older browsers, so although Websockets will be preferred, I am keeping polling as an option.
The way I have the websocket code set up is to:
Use Websockets to send the messages to the appropriate connections
Log the message in the database
The way the AJAX send works is:
Log the message in the database
The way the AJAX poll works is:
Check when user last retrieved messages for a room, and retrieve all messages since then
I have more of a conceptual question about how to get the two to work with each other. Assume I have User A and User B. If User A and User B are either both using AJAX polling or both using websockets, there are no issues whatsoever. It works as you would expect. But take the case when User A is using websockets and User B is using AJAX polling.
A → B
User A sends message via websocket
Chat message gets sent to all relevant connections. In this case, it just echoes back to User A, since User B is not using websockets.
Chat messages gets logged into database
User B requests new messages, and User A's message is sent back to him
B → A
User B sends message via AJAX
Message gets saved in database
?
This is what I'm hung up on. Websocket -> AJAX user messages work because the message ends up in the database where it can be polled by an AJAX user. But websocket users don't poll the database at all, so messages from AJAX users have no way of getting into the pipeline. Currently, websocket users don't see any messages from AJAX users. They only see them if they do a full page reload, at which point all messages get retrieved directly from the database.
What would be the appropriate method to allow some way for messages from AJAX users to get sent out via websocket to relevant websocket users? Basically, how can I communicate in the other direction?
The only thing I've been able to find on this subject is this slideshow - however, I'm not using longpolling, and I'm not entirely sure what it means by "providing that" to the websocket app. Does that mean put the onus on the websocket server to check for new AJAX messages? Is there no way to "push" from the AJAX script to the websocket server?
Thanks to ADyson for some ideas on how to approach this. This is what I ended up doing:
I have my JS clients ping the server every few seconds. For AJAX users, it's more frequent because they need to poll for messages. For Websocket users, they don't need to poll for websocket messages, so they poll every 15s to "check in". This has the benefit of functioning as an infinite loop essentially for each client, which is exactly what the idea requires.
What I did was essentially add a column to the messages table that keeps track of the message source: 0 for AJAX and 1 for WebSocket. Then, I modified the function that retrieves messages to take in an $ajaxOnly parameter. When I call this on an AJAX poll, it's false. For websocket polls, I call it with true instead. The result is for all rooms a user is in, it polls the DB and checks if there are any new AJAX messages. If there are, it sends them back to the client.
There are 2 caveats:
Messages will appear out of order. Websocket messages are relayed in realtime, so an AJAX message sent before a Websocket message could appear earlier to another AJAX user but later to other Websocket users.
This is not realtime. It's as slow as your poll interval, which in my case is 15 seconds for websockets since polls are very DB-intensive. AJAX polls are more frequent because they need to be to get any messages at all.
This isn't a perfect solution, but it does meet the goal of allowing AJAX messages to show up for websocket users in near-realtime. For me, I wanted to fully support AJAX and WebSocket, but AJAX is more for compatability and ideally most people will use WebSockets, so the fact that this isn't a great solution doesn't concern me too much, since it does get the job done.
If you were hoping for a realtime solution (like I was), you're going to be disappointed by this, but this is at least a workable solution so I've adopted it until something better comes up. You can make it near-realtime by increasing the frequency with which clients ping your server.
Simple solution:
When you save the message into the Datebase, push it to the Websocket Clients as well.
I am currently creating a stock market simulation and am working on the moment that the user logs into the simulation. I have a PHP script that will generate a certain price for a company four times and update it into my MySQL database while running. I currently have the following code:
PHP:
if (isset($_SESSION['userId']))
{
$isPlaying = 0;
while ($isPlaying <= 3)
{
$priceTemp = (rand(3300, 3700) / 100);
$sql = "UPDATE pricestemp SET price = $priceTemp WHERE companyName = 'Bawden';";
mysqli_query($conn, $sql);
sleep(1);
$isPlaying++;
}
echo '<h1>Welcome to the simulation</h1>';
}
I am aiming for these updates to happen in the background once the user has logged into the simulation. When refreshing my database every second, the updated prices are shown which is one of my objectives. However, what I would like it to do is still load the HTML onto the page (to say "Welcome to the simulation") while updating the database with every second with an updated price.
So far, when I log in, I have to wait 4 seconds before the HTML will load. In the future, I hope to have it consisently updating until a certain condition is met but when I have set an infinite loop earlier the HTML never loaded.
What do I have to do to allow the HTML to load once logged in and have the prices being generated and updated in the MySQL database in the background with no delay in either of these tasks happening?
You have a fundamental misunderstanding of how web-based requests work.
What you need to understand is that PHP is a server-side language. PHP generates any combination of HTML, CSS, JavaScript, JSON, or any other forms of data you want and sends it to your web browser when it's finished. While it's doing that, it can also manage data within a database or perform any other number of actions, but it will never send what the web browser can make use of until it finishes setting everything up. So if you're within an infinite loop, it will never finish and therefore nothing will be sent back to the web browser.
To remedy this, you need to use something called "asynchronous JavaScript", more commonly referred to as "ajax". Specifically, you first send some initial HTML to the web browser in one request and let the request end immediately. This allows the user to see something without waiting around for an indefinite period of time. Then, on the web browser end, you can use JavaScript to automatically send a second request to the server. During this second request to the server, you can perform your data processing and send back some data when you're finished to display to the user.
If you want to periodically update what you show the user, then you would repeat that second request to refresh what is shown on the user's webpage.
Any time you see some kind of "real-time" updating on a website, it's not coming from a single, persistently open connection to the web server--it's actually a series of repeated, broken up requests that periodically refresh what you see.
Broken down, standard web request workflows look something like this:
Web browser asks the web server for the webpage. Web browser waits for a reply.
Web server generates the webpage and sends the webpage to the web browser. Web server is done.
Web browser receives the webpage and shows it to the user. Web browser stops waiting for a reply.
Web browser runs any JavaScript it needs to run and requests data from the web server. Web browsers waits for a reply.
Web server processes the request and sends the requested data back to the web browser. Web server is done.
Web browser receives the requested data and updates the HTML on the webpage so the user can see it. Web browser stops waiting for a reply.
As you can see, each series of requests is 1) initiated by the web browser, 2) processed by the web server, and 3) any replies from the web server are then handled by the web browser after the web server is finished up. So each and every request goes browser -> server -> browser. If we add steps 7., 8., and 9. to the above, we will see them repeat the exact same pattern.
If you want to avoid adding JavaScript into the mix, preferring to refresh the entire page every time, then keep your data processing short. Optimize your database calls, fix your infrastructure (make sure your server and database have a LAN connection, that your hardware is good enough, etc.), make your code more efficient... do whatever you need to do to keep the processing time to a minimum.
This is all incredibly simplified and not 100% accurate, but should hopefully help you with your specific problem. The short version of all of this is: you can't show your HTML and process your data at the same time the way you're doing things now. You need to fundamentally change your workflow.
You have to do this in 2 network calls. The first network call should fetch the html. Then you have to use Javascript to fire another call to update your data. Once that api call returns it will update the html.
The scheduling model to manage the frequency of a background operation based on the frequency of requests at the front end is a very difficult problem. It's also a problem you don't need to solve. The data doesn't need to be changed when nobody is looking at it. You just need to store when the data was last looked at and apply greater deltas to older data.
I am creating a messaging system which have the following parts:
A form which send user message and upon submission of the form, PHP inserts the data into a MySQL Table called userMessages.
A PHP page which performs a MySQL Query select all from userMessages and displays all the messages.
The problem I'm having is making this messaging system have an INSTANT Message Functionality. i.e. I submit data from one form and it instantly appears on the user messages page WITHOUT having to manually refresh the page.
I do have temporary solution of refreshing the page every 20 second. But is there a way to update the messages page only at the moment a new message is submitted?
Pushing data to a web page is very hard, as Dan Grossman has said you will want to read that wiki article. AJAX polling every few seconds would be a good idea, if you don't mind a rather high server and database load. ama2 is also right - PHP is inherently not the best system for this, and a continuously running application server using, say, node.js, may be a lot more efficient.
Here is the scenario:
I have a page that is logging data to MYSQL. I have another page that reads that data and allows it to be viewed. When a new piece of data is logged I would like to have the first script check and see if the viewing page is open in the browser, and if so append the newest data to the end of the view. Also - could anyone point to some info giving an overview of how PHP and the browser interact? I think I have the concept of the DOM down for javascript...but as far as PHP it just appears that once the page is sent, that's it...
You're correct in that once the PHP is sent, that's it.
There is no way to send data to a PHP page once the page is loaded. There is another slightly nastier method, but the easiest way of doing this is going to be polling the page via Ajax.
So, have a script that every 20 seconds, sends a message to another PHP script that contains the timestamp of the last MySQL log you received, then get the script to return all the data that has been set by that time.
I'm unsure how new you are to JavaScript, but the easiest way of doing that is probably using JQuery's $.ajax and encoding the new MySQL records as JSON.
No this isn't possible as you describe. The viewing page will have to poll the server for changes, either by periodically reloading itself, or by javascript / AJAX.
You are right that once the page is sent by PHP it can have no further influence. In fact the PHP execution thread on the server is killed as soon as output is complete, so the thing that generated the page no longer even exists.
To expand on Dolondro's suggestion, rather than periodically polling the server for updates, you could use Server-Sent-Events (newly supported in modern browsers).
With these, you basically just send 1 ajax request to the server, and the connection is held open. Then, the server can send updates whenever it wants. When the browser receives an event, it can add the data to the screen. Even still, the connection is held open, and the server can send additional events/updates as they occur.
W3C page:
http://dev.w3.org/html5/eventsource/
Wikipedia:
http://en.wikipedia.org/wiki/Server-sent_events
More Info:
https://www.google.com/search?ix=hcb&sourceid=chrome&ie=UTF-8&q=server+sent+events
I've created a small jquery and php chatroom with some .get and .post functions and php docs that read and write data to a sql server. It works fine, but the small problem is when someone posts something, it takes about half a second for it to appear (because of the lag).
I fear there's something wrong with my coding.
im using
setinterval (listen, 300)
as my continuous jquery function for reading new db entries, listen is a function with a .get inside. How does stackoverflow or facebook do it so that the user types something in and immediately it pops out?
Maybe try displaying the inputted chat message immediately to the user who posted it, prior to posting it to the database.
Like this:
User enters message, submits
Update users chat window so they see it immediately
POST message to database
GET from db and update all chat windows
This can be implemented using various techniques, which have many names: Long-polling, Server Sent Events, Comet, WebSockets, and others.
Basic idea is this:
Alice opens facebook. Her browser makes a request for updates ($.get, for example), but the server does not respond if there are no new updates and the request remains in 'waiting' state.
Bob opens facebook. He decides to comment on Alice's wall. His browser posts his comment to the server ($.post).
The server accepts this post, handles it properly (saves onto Alice's wall, etc)
But ALSO server checks if there is a waiting update request from Alice. If there is, server renders info about this update into response stream and closes the connection.
Alice's browser finally gets a response to this long hanging request and happily draws a red "1" in the notification area. It also immediately opens another update request (to not miss any).
Alice sees comment from Bob, which was delivered instantly.
The technique described is called "long polling" and it was first introduced by Google in Gmail.
You can use HTML5 sockets, however these are very much in their infancy and not widely supported (i.e. by IE).
Lots of systems use Flash as a middle-man as that can hold a connection open.
With either of these you can use your PHP code that stores the comment to the database to also push this out to every "listener". This will be the quickest way possible. If your system is super clever it'll incorporate all three - HTML5 sockets where it can, Flash where it can't, and your regular polling were there's no Flash either.
http://pusher.com/ might be a good starting point for further learning.
Most sites that have fast chat use a technique called comet. You can read more about it here: http://ajaxian.com/archives/comet-a-new-approach-to-ajax-applications
It essentially is a piece of modified server software that waits to return a response to the user until either a message is sent or it is about to timeout.