web-dev-qa-db-fra.com

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

Je me suis récemment mis à la recherche d'un bon moyen de communiquer entre nodeJS et PHP. Voici l’idée: nodeJS est encore tout à fait nouveau et il peut être assez délicat de développer une application complète uniquement avec elle. De plus, vous n’en aurez peut-être besoin que pour un module de votre projet, comme les notifications en temps réel, le chat, etc. les frameworks existants, comme CodeIgniter ou Symfony).

J'aimerais avoir une solution facile. Je ne veux pas utiliser cURL, ni un troisième serveur pour communiquer entre Apache et les serveurs Node. Ce que je veux, c'est pouvoir attraper les événements d'un nœud en Javascript simple, côté client.

Je n'ai trouvé aucune réponse complète, la plupart du temps côté client était exécuté par le serveur de noeud et n'était donc pas applicable dans mon cas. J'ai donc exploré tous les sujets possibles et j'ai finalement trouvé ma réponse. Je vais essayer de partager cela et de faire en sorte que tout soit clair.

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

98
Jérémy Dutheil

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

C'est un exemple de projet très simple: une discussion en ligne. Vous avez juste un auteur et un message, et lorsque vous appuyez sur envoyer, celui-ci 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 allons utiliser nodeJS pour cela.

Je ne parlerai pas du code PHP, il est très 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, assurez-vous donc d'installer ces modules avec npm. Ensuite, nous créons un serveur nodeJS simple:

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 rappel d'événements lorsqu'un nouvel utilisateur est connecté; chaque fois que nous recevons un message (représente un message de discussion), 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, parce que je ne savais pas quel script inclure pour pouvoir exécuter du code Socket.IO sans le nodeServer (car la page du 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 PHP page, 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 noeudClient.js, où nous nous connectons simplement au serveur de noeud et attendons que l'événement mette à 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 );
});

J'essaierai de mettre à jour et d'améliorer mon code dès que possible, mais je pense qu'il est déjà ouvert à toutes les bonnes choses! Je suis vraiment ouvert aux conseils et critiques sur ce sujet, est-ce la bonne façon de le faire, ..?

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

130
Jérémy Dutheil

J'ai une autre solution qui fonctionne assez bien pour moi, mais j'aimerais que quelqu'un commente sur son efficacité, car je n'ai pas (encore) eu l'occasion/le temps de la tester sur le vrai serveur.

Voici le code node-js. Je mets ce code dans un fichier nommé 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 à l'aide de file_get_contents ():

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

Fonctionne très bien, lorsque je charge la page php, il appelle à son tour la page nodeserver.js, qui jsonifie le knall-object.

J'ai deux installations localhost fonctionnant sur iis sous Windows 10, un serveur php standard, et le serveur nodejs fonctionne avec le paquetage ordonné iisnode .

Le "vrai" serveur est exécuté sur Ubuntu.

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

2
Snorvarg

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


Sur votre page:

  • Charge Socket JS

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

  • Faire objet de la prise

var socket = io ();

  • Utilisez la fonction emit pour envoyer des données au serveur de noeuds.

socket.emit ('new_notification', {
message: 'message',
titre: 'titre',
icon: 'icon',
});

Alors maintenant, votre code va ressembler

<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 sur Node le gestionnaire de production côté serveur pour votre demande afin d'obtenir votre demande et d'envoyer un message à tous les périphériques/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;
}
0
vikujangid