97 votes

Comment intégrer nodeJS + Socket.IO et PHP ?

J'ai récemment cherché à trouver un bon moyen de communiquer entre nodeJS et PHP. Voici l'idée : nodeJS est encore assez nouveau, et il peut être assez délicat de développer une application complète uniquement avec lui. De plus, vous pouvez n'en avoir besoin que pour un seul module de votre projet, comme les notifications en temps réel, le chat, ... Et vous voulez gérer tous les autres modules avec PHP, parce que c'est probablement plus facile pour vous (et vous pouvez profiter des frameworks existants, comme CodeIgniter ou Symfony).

J'aimerais avoir une solution facile ; je ne veux pas utiliser cURL, ou un troisième serveur pour communiquer entre les serveurs Apache et Node. Ce que je veux, c'est être capable d'attraper les événements de Node en Javascript simple, côté client.

Je n'ai pas trouvé de réponses complètes, la plupart du temps le côté client était exécuté par le serveur de nœuds et donc non applicable dans mon cas. J'ai donc exploré tous les sujets possibles, et j'ai finalement trouvé ma réponse ; je vais essayer de la partager, et d'avoir un point où tout est clair.

J'espère que cela pourra aider certaines personnes ;)

131voto

Jérémy Dutheil Points 1628

Donc, pour commencer, j'ai mis mon projet sur github, si vous voulez avoir accès au code complet : https://github.com/jdutheil/nodePHP

Il s'agit d'un projet d'exemple très simple : un chat web. Vous avez juste un auteur et un message, et quand vous appuyez sur envoyer, il est enregistré dans une base de données mysql. L'idée est d'envoyer des mises à jour en temps réel, et d'avoir une vraie conversation ;) Nous utiliserons nodeJS pour cela.

Je ne parlerai pas du code PHP, il est vraiment simple et sans intérêt ici ; ce que je veux vous montrer, c'est comment intégrer votre code nodeJS.

J'utilise express et Socket.IO, donc assurez-vous d'installer ces modules avec npm. Ensuite, nous créons un simple serveur nodeJS :

var socket = require( 'socket.io' );
var express = require( 'express' );
var http = require( 'http' );

var app = express();
var server = http.createServer( app );

var io = socket.listen( server );

io.sockets.on( 'connection', function( client ) {
    console.log( "New client !" );

    client.on( 'message', function( data ) {
        console.log( 'Message received ' + data.name + ":" + data.message );

        io.sockets.emit( 'message', { name: data.name, message: data.message } );
    });
});

server.listen( 8080 );

Nous avons enregistré notre callback d'événements lorsqu'un nouvel utilisateur est connecté ; chaque fois que nous recevons un message (représentant un message de chat), nous le diffusons à tous les utilisateurs connectés. Maintenant, la partie délicate : côté client ! C'est la partie qui m'a pris le plus de temps, car je ne savais pas quel script inclure pour pouvoir exécuter le code Socket.IO sans le nodeServer (car la page client sera servie par Apache).

Mais tout est déjà fait ; lorsque vous installez le module Socket.IO avec npm, un script est disponible dans /node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js ; que le script que nous allons inclure dans notre page PHP, dans mon cas :

    <script src="js/node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js"></script>
    <script src="js/nodeClient.js"></script>

Et pour finir, mon nodeClient.js, où nous nous connectons simplement au serveur node et attendons un événement pour mettre à jour notre page ;)

var socket = io.connect( 'http://localhost:8080' );

$( "#messageForm" ).submit( function() {
    var nameVal = $( "#nameInput" ).val();
    var msg = $( "#messageInput" ).val();

    socket.emit( 'message', { name: nameVal, message: msg } );

    // Ajax call for saving datas
    $.ajax({
        url: "./ajax/insertNewMessage.php",
        type: "POST",
        data: { name: nameVal, message: msg },
        success: function(data) {

        }
    });

    return false;
});

socket.on( 'message', function( data ) {
    var actualContent = $( "#messages" ).html();
    var newMsgContent = '<li> <strong>' + data.name + '</strong> : ' + data.message + '</li>';
    var content = newMsgContent + actualContent;

    $( "#messages" ).html( content );
});

Je vais essayer de mettre à jour et d'améliorer mon code dès que possible, mais je pense qu'il est déjà ouvert à toutes sortes de choses cool ! Je suis vraiment ouvert aux conseils et aux critiques sur ce genre de choses, est-ce la bonne façon de faire, ?

J'espère que cela pourra aider certaines personnes !

2voto

Snorvarg Points 13

J'ai une autre solution qui fonctionne assez bien pour moi, mais j'aimerais que quelqu'un me dise à quel point elle est efficace, car je n'ai pas (encore) eu l'occasion/le temps de la tester sur le vrai serveur.

Voici le code de node-js. Je mets ce code dans un fichier appelé nodeserver.js :

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});

    var knall = new Object();
    knall.totten = "4 tomtar";
    knall.theArr = new Array();
    knall.theArr.push("hoppla")
    knall.theArr.push("hej")
    var strKnall = JSON.stringify(knall);

    res.end(strKnall);
}).listen(process.env.PORT);  

Et voici le simple morceau de code en php, appelant le serveur node-js avec l'aide de file_get_contents() :

$json = file_get_contents('http://localhost:3002/knall.json');
$obj = json_decode($json);

Cela fonctionne très bien, lorsque je charge la page php, elle appelle à son tour la page nodeserver.js, qui jsonifie l'objet knall.

J'ai deux installations locales qui tournent sur iis sous Windows 10, un serveur php standard et un serveur nodejs qui fonctionne avec le système de gestion de la qualité. iisnode paquet.

Le "vrai" serveur fonctionne sous Ubuntu.

Je pense que c'est une solution simple et efficace pour la communication entre deux serveurs, mais peut-être que quelqu'un a des commentaires à faire à ce sujet ?

0voto

vikujangid Points 708

Essayez de le faire ou vous pouvez consulter mon blog pour exemple complet de code sur nodejs


Du côté de votre page :

  • Charger Socket JS

https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js

  • Faire l'objet de la prise

var socket = io() ;

  • Utilisez le emit pour envoyer des données à nodeserver.

socket.emit('new_notification', {
message : "message",
titre : "titre",
icône : "icône",
}) ;

Donc maintenant votre code sera comme suit

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>

var socket = io(); 

$(document).ready(function($) {
  $('.rules-table').on('click', '.runRule', function(event) {
    event.preventDefault();
    /* Act on the event */
    var ruleID = $(this).parents('tr').attr('id');

    // send notification before going to post 
    socket.emit('new_notification', {
        message: 'Messge is ready to sent',
        title: title,
        icon: icon,
    });
    $.ajax({
      url: '/ajax/run-rule.php',
      type: 'POST',
      dataType: 'json',
      data: {
        ruleID: ruleID
      },
    })
    .done(function(data) {
      console.log(data);

      // send notification when post success 
      socket.emit('new_notification', {
        message: 'Messge was sent',
        title: title,
        icon: icon,
      });

    })
    .fail(function() {
      console.log("error");

      // send notification when post failed 
      socket.emit('new_notification', {
        message: 'Messge was failed',
        title: title,
        icon: icon,
      });
    })
    .always(function() {
      console.log("complete");
    });

  });
});

Maintenant, du côté du serveur Node, créez un gestionnaire pour votre demande afin de recevoir votre demande et d'envoyer un message à tous les appareils/navigateurs connectés (server.js).

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res) {
   res.sendfile('index.html');
});

io.on('connection', function (socket) {
  socket.on( 'new_notification', function( data ) {
    console.log(data.title,data.message);

    // Now Emit this message to all connected devices
    io.sockets.emit( 'show_notification', { 
      title: data.title, 
      message: data.message, 
      icon: data.icon, 
    });
  });
});

http.listen(3000, function() {
   console.log('listening on localhost:3000');
});

Maintenant le côté client/navigateur/client fait un récepteur pour recevoir le message de socket du serveur de noeud

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>   

var socket = io();

/**
 * Set Default Socket For Show Notification
 * @param {type} data
 * @returns {undefined}
 */
socket.on('show_notification', function (data) {
    showDesktopNotification(data.title, data.message, data.icon);
});
/**
 * Set Notification Request
 * @type type
 */
function setNotification() {
    showDesktopNotification('Lokesh', 'Desktop Notification..!', '/index.jpeg');
    sendNodeNotification('Lokesh', 'Browser Notification..!', '/index.jpeg');
}
/**
 * Check Browser Notification Permission
 * @type window.Notification|Window.Notification|window.webkitNotification|Window.webkitNotification|Window.mozNotification|window.mozNotification
 */
var Notification = window.Notification || window.mozNotification || window.webkitNotification;
Notification.requestPermission(function (permission) {
});
/**
 * Request Browser Notification Permission 
 * @type Arguments
 */
function requestNotificationPermissions() {
    if (Notification.permission !== 'denied') {
        Notification.requestPermission(function (permission) {
        });
    }
}
/**
 * Show Desktop Notification If Notification Allow
 * @param {type} title
 * @param {type} message
 * @param {type} icon
 * @returns {undefined}
 */
function showDesktopNotification(message, body, icon, sound, timeout) {
    if (!timeout) {
        timeout = 4000;
    }
    requestNotificationPermissions();
    var instance = new Notification(
            message, {
                body: body,
                icon: icon,
                sound: sound
            }
    );
    instance.onclick = function () {
        // Something to do
    };
    instance.onerror = function () {
        // Something to do
    };
    instance.onshow = function () {
        // Something to do
    };
    instance.onclose = function () {
        // Something to do
    };
    if (sound)
    {
        instance.sound;
    }
    setTimeout(instance.close.bind(instance), timeout);
    return false;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X