How to implement a chat room using Jquery/PHP?

泪湿孤枕 提交于 2019-11-27 10:30:26
Wouter Dorgelo

Chat with PHP/AJAX/JSON

I used this book/tutorial to write my chat application:

AJAX and PHP: Building Responsive Web Applications: Chapter 5: AJAX chat and JSON.

It shows how to write a complete chat script from scratch.


Comet based chat

You can also use Comet with PHP.

From: zeitoun:

Comet enables web servers to send data to the client without having any need for the client to request it. Therefor, this technique will produce more responsive applications than classic AJAX. In classic AJAX applications, web browser (client) cannot be notified in real time that the server data model has changed. The user must create a request (for example by clicking on a link) or a periodic AJAX request must happen in order to get new data fro the server.

I'll show you two ways to implement Comet with PHP. For example:

  1. based on hidden <iframe> using server timestamp
  2. based on a classic AJAX non-returning request

The first shows the server date in real time on the clients, the displays a mini-chat.

Method 1: iframe + server timestamp

You need:

  • a backend PHP script to handle the persistent http request backend.php
  • a frondend HTML script load Javascript code index.html
  • the prototype JS library, but you can also use jQuery

The backend script (backend.php) will do an infinite loop and will return the server time as long as the client is connected.

<?php
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sun, 5 Mar 2012 05:00:00 GMT");
flush();
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <title>Comet php backend</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>

<body>
<script type="text/javascript">
// KHTML browser don't share javascripts between iframes
var is_khtml = navigator.appName.match("Konqueror") || navigator.appVersion.match("KHTML");
if (is_khtml)
{
  var prototypejs = document.createElement('script');
  prototypejs.setAttribute('type','text/javascript');
  prototypejs.setAttribute('src','prototype.js');
  var head = document.getElementsByTagName('head');
  head[0].appendChild(prototypejs);
}
// load the comet object
var comet = window.parent.comet;
</script>

<?php
while(1) {
    echo '<script type="text/javascript">';
    echo 'comet.printServerTime('.time().');';
    echo '</script>';
    flush(); // used to send the echoed data to the client
    sleep(1); // a little break to unload the server CPU
}
?>
</body>
</html>

The frontend script (index.html) creates a "comet" javascript object that will connect the backend script to the time container tag.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Comet demo</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <script type="text/javascript" src="prototype.js"></script>

</head>
<body>
  <div id="content">The server time will be shown here</div>

<script type="text/javascript">
var comet = {
connection   : false,
iframediv    : false,

initialize: function() {
  if (navigator.appVersion.indexOf("MSIE") != -1) {

    // For IE browsers
    comet.connection = new ActiveXObject("htmlfile");
    comet.connection.open();
    comet.connection.write("<html>");
    comet.connection.write("<script>document.domain = '"+document.domain+"'");
    comet.connection.write("</html>");
    comet.connection.close();
    comet.iframediv = comet.connection.createElement("div");
    comet.connection.appendChild(comet.iframediv);
    comet.connection.parentWindow.comet = comet;
    comet.iframediv.innerHTML = "<iframe id='comet_iframe' src='./backend.php'></iframe>";

  } else if (navigator.appVersion.indexOf("KHTML") != -1) {

    // for KHTML browsers
    comet.connection = document.createElement('iframe');
    comet.connection.setAttribute('id',     'comet_iframe');
    comet.connection.setAttribute('src',    './backend.php');
    with (comet.connection.style) {
      position   = "absolute";
      left       = top   = "-100px";
      height     = width = "1px";
      visibility = "hidden";
    }
    document.body.appendChild(comet.connection);

  } else {

    // For other browser (Firefox...)
    comet.connection = document.createElement('iframe');
    comet.connection.setAttribute('id',     'comet_iframe');
    with (comet.connection.style) {
      left       = top   = "-100px";
      height     = width = "1px";
      visibility = "hidden";
      display    = 'none';
    }
    comet.iframediv = document.createElement('iframe');
    comet.iframediv.setAttribute('src', './backend.php');
    comet.connection.appendChild(comet.iframediv);
    document.body.appendChild(comet.connection);

  }
},

// this function will be called from backend.php  
printServerTime: function (time) {
  $('content').innerHTML = time;
},

onUnload: function() {
  if (comet.connection) {
    comet.connection = false; // release the iframe to prevent problems with IE when reloading the page
  }
}
}
Event.observe(window, "load",   comet.initialize);
Event.observe(window, "unload", comet.onUnload);

</script>

</body>
</html>

Method 2: AJAX non-returning request

You need the same as in method 1 + a file for dataexchange (data.txt)

Now, backend.php will do 2 things:

  1. Write into "data.txt" when new messages are sent
  2. Do an infinite loop as long as "data.txt" file is unchanged
<?php
$filename  = dirname(__FILE__).'/data.txt';

// store new message in the file
$msg = isset($_GET['msg']) ? $_GET['msg'] : '';
if ($msg != '')
{
    file_put_contents($filename,$msg);
    die();
}

// infinite loop until the data file is not modified
$lastmodif    = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;
$currentmodif = filemtime($filename);
while ($currentmodif <= $lastmodif) // check if the data file has been modified
{
    usleep(10000); // sleep 10ms to unload the CPU
    clearstatcache();
    $currentmodif = filemtime($filename);
}

// return a json array
$response = array();
$response['msg']       = file_get_contents($filename);
$response['timestamp'] = $currentmodif;
echo json_encode($response);
flush();
?>

The frontend script (index.html) creates the <div id="content"></div> tags hat will contains the chat messages comming from "data.txt" file, and finally it create a "comet" javascript object that will call the backend script in order to watch for new chat messages.

The comet object will send AJAX requests each time a new message has been received and each time a new message is posted. The persistent connection is only used to watch for new messages. A timestamp url parameter is used to identify the last requested message, so that the server will return only when the "data.txt" timestamp is newer that the client timestamp.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Comet demo</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <script type="text/javascript" src="prototype.js"></script>
</head>
<body>

<div id="content">
</div>

<p>
<form action="" method="get" onsubmit="comet.doRequest($('word').value);$('word').value='';return false;">
  <input type="text" name="word" id="word" value="" />
  <input type="submit" name="submit" value="Send" />
</form>
</p>

<script type="text/javascript">
var Comet = Class.create();
Comet.prototype = {

timestamp: 0,
url: './backend.php',
noerror: true,

initialize: function() { },

connect: function()
{
  this.ajax = new Ajax.Request(this.url, {
    method: 'get',
    parameters: { 'timestamp' : this.timestamp },
    onSuccess: function(transport) {
      // handle the server response
      var response = transport.responseText.evalJSON();
      this.comet.timestamp = response['timestamp'];
      this.comet.handleResponse(response);
      this.comet.noerror = true;
    },
    onComplete: function(transport) {
      // send a new ajax request when this request is finished
      if (!this.comet.noerror)
        // if a connection problem occurs, try to reconnect each 5 seconds
        setTimeout(function(){ comet.connect() }, 5000); 
      else
        this.comet.connect();
      this.comet.noerror = false;
    }
  });
  this.ajax.comet = this;
},

disconnect: function()
{
},

handleResponse: function(response)
{
  $('content').innerHTML += '<div>' + response['msg'] + '</div>';
},

doRequest: function(request)
{
  new Ajax.Request(this.url, {
    method: 'get',
    parameters: { 'msg' : request 
  });
}
}
var comet = new Comet();
comet.connect();
</script>

</body>
</html>

Alternatively

You can also have a look at other chat applications to see how they did it:

Chris Cinelli

Polling is not a good idea. You need a solution that use long polling or web sockets.

http://hookbox.org is probably the best tool you can use.

It is a box that lives between the server and the browsers and manages abstractions called channels (think about an IRC channel). It is open source on github: https://github.com/hookbox/hookbox The box is written in Python but it can easily be used with a server written in any language. It also come with a Javascript library that is built on jsio (uses websockets, long-polling, or whatever is the best technology available on the browser) that guarantee that it uses the best technology available in the browsers.In a demo I saw a realtime chat implemented with few line of code.

Hookbox’s purpose is to ease the development of real-time web applications, with an emphasis on tight integration with existing web technology. Put simply, Hookbox is a web-enabled message queue. Browers may directly connect to Hookbox, subscribe to named channels, and publish and receive messages on those channels in real-time. An external application (typically the web application itself) may also publish messages to channels by means of the Hookbox REST interface. All authentication and authorization is performed by an external web application via designated “webhook” callbacks.

Any time a user connects or operates on a channel, ( subscribe, publish, unsubscribe) Hookbox makes an http request to the web application for authorization for the action. Once subscribed to a channel, the user’s browser will receive real-time events that originate either in another browser via the javascript api, or from the web application via the REST api.

They key insight is that all application development with hookbox Happens either in javascript, or in the native language of the web application itself (e.g. PHP.)

You need a server that can run Python BUT you do NOT have to know Python.

If instead you want to use just websockets and PHP this is good starting point: http://blancer.com/tutorials/69066/start-using-html5-websockets-today/

Have you looked at PHPDaemon, which is written with active usage of libevent and pnctl? It has lots of features and even simple chat demo application. Even it has some production implementations.

this could be a good starting point

http://css-tricks.com/jquery-php-chat/

I suggest to implement it with HTML5 WebSockets, with long polling or comet as a fallback for older browsers. WebSockets open a persistent connection to the browser. There is an open source php implementation of a websocket server.

Gabriel Croitoru

I believe the problem you are looking at requires the use of comet web programming. You can find more details on wikipedia, by searching for Comet programming, and on Ajaxian (I'm still new to this site and I can't post more than 1 link in the response).

The problem is that this can't be easily achieved with php on the server side. More details: using comet with php

Also, if you search on google for 'php comet' you'll find a tutorial to achieve the desired effect.

LATER EDIT

Ape project

Implemented a project using this engine. Is great.

Comet with php

Hope this helps, Gabriel

I know this is very late, but here

EDIT: Updated link

This looks promising! Might even be super easy to restyle :)

http://www.php-development.ru/javascripts/ajax-chat.php

Ajax Chat script in Javascript/PHP

Description

Ajax Chat is a light-weight customizable web chat software implemented in JavaScript and PHP. The script does not require Java, Flash, or any other plugins.

Features

  • Public and private chat.
  • Login as a registered user or as a guest.
  • Away status, custom colors, smileys, user gender/status icons.
  • Ajax Chat can be integrated with a third-party membership system by implementing user authentication routine. Advanced integration options: if user is logged in to the website, he can be logged in to the chat automatically.

*Please note that this is a copy/paste from the original site.

I haven't done it with PHP before but you're best bet would probably be some kind of socket connection. Here's the PHP manual for sockets.

I don't remember who's tutorial it was but I made a chat room like what you want using Flash for the client and Java for the server. I think this link might be where the tutorial was and it may help you out.

I suggest you to try Socket.IO together with NodeJS. Socket.IO gives you a nice and very easy client API, works on most modern browsers and uses appropriate transport where possible (Websocket, long polling, etc). NodeJS is a server-side daemon, which holds HTTP connections. Official site of the Socket.IO contains information on how to use them together. Hope it will help you.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!