web-dev-qa-db-fra.com

Comment implémenter une salle de discussion avec Jquery/PHP?

Je cherche à implémenter une salle de discussion en utilisant PHP/Javascript (Jquery) avec les fonctionnalités de discussion de groupe et de discussion privée.

Le problème est de savoir comment mettre continuellement à jour l'interface de manière naturelle et éventuellement aussi montrer aux messages 'X is Typing ..' dans une discussion privée.

Le moyen évident semble être que toutes les X secondes/millisecondes, le javascript envoie une requête ping au serveur et récupère une liste de nouveaux messages entre le dernier ping et maintenant. Cependant, cela peut rendre l’interface un peu artificielle si, soudainement, la salle de discussion est inondée de 5 messages. Je préférerais que chaque message apparaisse tel qu'il est tapé.

Existe-t-il un moyen pour le javascript de maintenir une connexion continue au serveur, le serveur envoie tous les nouveaux messages à cette connexion et le javascript les ajoute à l'interface pour qu'ils apparaissent simultanément, presque aussitôt que le serveur les reçoit?

Je sais qu'il existe certaines options de sondage qui vous obligent à installer des modules Apache, etc., mais je ne suis pas un administrateur système; par conséquent, je préférerais une solution très facile à installer sur un compte d'hébergement partagé ou un compte php./mysql seule solution.

26
Click Upvote

Discuter avec PHP/AJAX/JSON

J'ai utilisé ce livre/tutoriel pour écrire mon application de chat: 

AJAX et PHP: Création d'applications Web réactives: Chapitre 5: AJAX discussion et JSON

Il montre comment écrire un script de discussion complet à partir de zéro.


Chat basé sur la comète

Vous pouvez également utiliser Comet avec PHP .

De: zeitoun :

Comet permet aux serveurs Web d'envoyer des données au client sans que le client ait besoin de les demander. Par conséquent, cette technique produira des applications plus réactives que AJAX classique. Dans les applications classiques AJAX, le navigateur Web (client) ne peut pas être averti en temps réel de la modification du modèle de données du serveur. L'utilisateur doit créer une demande (par exemple en cliquant sur un lien) ou une demande périodique AJAX pour obtenir de nouvelles données du serveur. 

Je vais vous montrer deux manières d'implémenter Comet avec PHP. Par exemple:

  1. basé sur <iframe> caché en utilisant l'horodatage du serveur
  2. basé sur une demande classique AJAX non-retour

Le premier affiche la date du serveur en temps réel sur les clients, puis affiche une mini-discussion. 

Méthode 1: iframe + horodatage du serveur

Vous avez besoin:

  • un script backend PHP pour gérer la requête http persistante backend.php
  • un script HTML frondend charger le code Javascript index.html
  • la prototype de bibliothèque JS , mais vous pouvez également utiliser jQuery

Le script backend (backend.php) effectuera une boucle infinie et renverra l'heure du serveur tant que le client est connecté.

<?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>

Le script frontend (index.html) crée un objet javascript "comet" qui connectera le script backend à la balise de conteneur de temps. 

<!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>

Méthode 2: AJAX demande non renvoyée

Vous avez besoin de la même chose que dans la méthode 1 + un fichier pour dataexchange (data.txt)

Maintenant, backend.php fera 2 choses: 

  1. Ecrire dans "data.txt" lorsque de nouveaux messages sont envoyés
  2. Faire une boucle infinie tant que le fichier "data.txt" est inchangé
<?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();
?>

Le script frontend (index.html) crée les balises <div id="content"></div> qui contiendront les messages de discussion provenant du fichier "data.txt" et, enfin, il créera un objet javascript "comète" qui appellera le script principal afin de surveiller les nouveaux messages.

L'objet comète enverra des requêtes AJAX chaque fois qu'un nouveau message aura été reçu et qu'un nouveau message sera publié. La connexion persistante est uniquement utilisée pour surveiller les nouveaux messages. Un paramètre d'URL d'horodatage est utilisé pour identifier le dernier message demandé, de sorte que le serveur ne retourne que lorsque l'horodatage "data.txt" est plus récent que l'horodatage du client. 

<!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>

Alternativement

Vous pouvez également consulter d'autres applications de discussion pour voir comment elles ont fonctionné: 

45
Wouter Dorgelo

Les sondages ne sont pas une bonne idée. Vous avez besoin d’une solution qui utilise de longues sessions d’interrogation ou Web.

http://hookbox.org est probablement le meilleur outil que vous puissiez utiliser.

C'est une boîte qui vit entre le serveur et les navigateurs et gère des abstractions appelées canaux (pensez à un canal IRC). Il est open source sur github: https://github.com/hookbox/hookbox La boîte est écrite en Python, mais elle peut facilement être utilisée avec un serveur écrit dans n’importe quel langage. Il est également livré avec une bibliothèque Javascript construite sur jsio (utilise des Websockets, des interrogations longues ou toute autre technologie constituant la meilleure technologie disponible sur le navigateur) garantissant l’utilisation de la meilleure technologie disponible dans les navigateurs.Dans une démo, j’ai vu chat en temps réel implémenté avec quelques lignes de code.

Le but de Hookbox est de faciliter le développement d’applications Web en temps réel, en mettant l’accent sur une intégration étroite à la technologie Web existante. En termes simples, Hookbox est une file d'attente de messages compatible Web. Browers peut se connecter directement à Hookbox, s'abonner à des canaux nommés et publier et recevoir des messages sur ces canaux en temps réel. Une application externe (généralement l’application Web elle-même) peut également publier des messages sur des canaux au moyen de l’interface Hookbox REST. Toutes les authentifications et autorisations sont effectuées par une application Web externe via des rappels désignés «Webhook».

alt text

Chaque fois qu'un utilisateur se connecte ou opère sur un canal (abonnement, publication, désinscription), Hookbox envoie une demande http à l'application Web pour obtenir l'autorisation de l'action. Une fois abonné à un canal, le navigateur de l'utilisateur recevra les événements en temps réel qui proviennent soit d'un autre navigateur via l'API javascript, soit de l'application Web via l'API REST.

L’idée clé est que tout développement d’applications avec hookbox se produit soit en javascript, soit dans la langue native de l’application Web elle-même (par exemple, PHP).

Vous avez besoin d'un serveur capable d'exécuter Python MAIS vous n'avez PAS besoin de connaître Python.

Si vous préférez utiliser uniquement websockets et PHP, c'est un bon point de départ: http://blancer.com/tutorials/69066/start-using-html5-websockets-today/

6
Chris Cinelli

cela pourrait être un bon point de départ

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

2
fcalderan

Je suggère de l'implémenter avec HTML5 WebSockets, avec une longue interrogation ou une comète comme solution de secours pour les anciens navigateurs. WebSockets ouvre une connexion persistante au navigateur. Il existe une implémentation open source php d’un serveur websocket .

2
Gipsy King

Avez-vous regardé PHPDaemon , qui est écrit avec une utilisation active de libevent et pnctl? Il a beaucoup de fonctionnalités et même simple chat application de démonstration. Même il a quelques implémentations de production.

2
nefo_x

Cela semble prometteur! Pourrait même être super facile à relooker :)

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

Ajax Chat script en Javascript/PHP

La description

Ajax Chat est un logiciel de chat Web léger et personnalisable implémenté en JavaScript et PHP. Le script ne nécessite pas Java, Flash ou tout autre plugin.

Caractéristiques

  • Chat public et privé.
  • Connectez-vous en tant qu'utilisateur enregistré ou en tant qu'invité.
  • Statut Absent, couleurs personnalisées, smileys, icônes de sexe/statut de l'utilisateur.
  • Ajax Chat peut être intégré à un système d’appartenance tiers en mettant en œuvre une routine d’authentification des utilisateurs. Options d'intégration avancées: si l'utilisateur est connecté au site Web, il peut le faire automatiquement.

Ajax lightweight chat script

* Veuillez noter qu'il s'agit d'un copier/coller de le site d'origine .

1
Qwerty

Je crois que le problème que vous étudiez nécessite l'utilisation de la programmation Web de comètes. Vous pouvez trouver plus de détails sur wikipedia, en recherchant la programmation Comet, et sur Ajaxian (je suis encore nouveau sur ce site et je ne peux pas poster plus d'un lien dans la réponse).

Le problème est que cela ne peut pas être facilement réalisé avec php côté serveur. Plus de détails: en utilisant la comète avec php

En outre, si vous recherchez «php comet» sur Google, vous trouverez un didacticiel pour obtenir l'effet souhaité.

PLUS TARD

Projet Ape

Implémenter un projet en utilisant ce moteur. C'est génial.

Comète avec php

J'espère que cela vous aidera, Gabriel

1
Gabriel Croitoru

Je sais que c'est très tard, mais ici

EDIT: lien mis à jour

1
Aditya Goturu

Je vous suggère d'essayer Socket.IO avec NodeJS . Socket.IO vous fournit une API client agréable et très simple, fonctionne sur la plupart des navigateurs modernes et utilise le transport approprié dans la mesure du possible (Websocket, longue interrogation, etc.). NodeJS est un démon côté serveur, qui contient les connexions HTTP. Le site officiel du Socket.IO contient des informations sur la façon de les utiliser ensemble. J'espère que cela vous aidera.

0
galymzhan

Je ne l'avais pas encore fait avec PHP, mais vous feriez mieux de parier avec une sorte de connexion socket. Voici le PHP manual pour les sockets. 

Je ne me souviens plus de qui était le didacticiel, mais j’ai créé une salle de discussion comme vous le souhaitez, à l’aide de Flash pour le client et de Java pour le serveur. Je pense que ce lien pourrait être là où se trouvait le tutoriel et cela pourrait vous aider.

0
Aaron Hathaway