Wie kann man nodeJS + Socket.IO und PHP integrieren?


98

Ich habe mich kürzlich umgesehen, um einen guten Weg zu finden, um zwischen nodeJS und PHP zu kommunizieren. Hier ist die Idee: nodeJS ist noch ziemlich neu und es kann schwierig sein, eine vollständige Anwendung nur damit zu entwickeln. Darüber hinaus benötigen Sie es möglicherweise nur für ein Modul Ihres Projekts, wie Echtzeitbenachrichtigungen, Chat usw. Und Sie möchten alle anderen Dinge mit PHP verwalten, da es für Sie wahrscheinlich einfacher ist (und Sie davon profitieren können) die vorhandenen Frameworks wie CodeIgniter oder Symfony).

Ich hätte gerne eine einfache Lösung. Ich möchte weder cURL noch einen dritten Server für die Kommunikation zwischen Apache- und Node-Servern verwenden. Ich möchte in der Lage sein, Ereignisse vom Knoten in einfachem Javascript auf der Clientseite abzufangen.

Ich habe keine Antworten gefunden, die vollständig waren, die meiste Zeit clientseitig vom Knotenserver ausgeführt wurden und daher in meinem Fall nicht zutreffen. Also habe ich alle möglichen Themen gecrawlt und endlich meine Antwort gefunden; Ich werde versuchen, dies zu teilen und einen Punkt zu haben, an dem alles klar ist.

Hoffe das kann einigen Leuten helfen! ;)

Antworten:


131

Zunächst stelle ich mein Projekt auf github, wenn Sie auf den vollständigen Code zugreifen möchten: https://github.com/jdutheil/nodePHP

Es ist ein sehr einfaches Beispielprojekt: ein Web-Chat. Sie haben nur einen Autor und eine Nachricht, und wenn Sie auf Senden klicken, wird diese in einer MySQL-Datenbank gespeichert. Die Idee ist, Aktualisierungen in Echtzeit zu senden und ein echtes Gespräch zu führen. ;) Dafür verwenden wir nodeJS.

Ich werde nicht über PHP-Code sprechen, es ist wirklich einfach und hier nicht interessant; Ich möchte Ihnen zeigen, wie Sie Ihren nodeJS-Code integrieren.

Ich benutze Express und Socket.IO, also installiere diese Module unbedingt mit npm. Dann erstellen wir einen einfachen NodeJS-Server:

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 );

Wir haben unseren Ereignisrückruf registriert, wenn ein neuer Benutzer verbunden ist. Jedes Mal, wenn wir eine Nachricht erhalten (die eine Chat-Nachricht darstellt), senden wir sie an alle verbundenen Benutzer. Nun der knifflige Teil: clientseitig! Das war der Teil, der mich die meiste Zeit gekostet hat, weil ich nicht wusste, welches Skript enthalten ist, um Socket.IO-Code ohne den nodeServer ausführen zu können (da die Client-Seite von Apache bereitgestellt wird).

Aber alles ist schon erledigt; Wenn Sie das Socket.IO-Modul mit npm installieren, ist ein Skript in verfügbar /node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js. dass das Skript, das wir in unsere PHP-Seite aufnehmen werden, in meinem Fall:

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

Und zum Schluss meine nodeClient.js, wo wir einfach eine Verbindung zum Knotenserver herstellen und auf das Ereignis warten, um unsere Seite zu aktualisieren. ;)

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 );
});

Ich werde versuchen, meinen Code so schnell wie möglich zu aktualisieren und zu verbessern, aber ich denke, er ist bereits offen für alle coolen Dinge! Ich bin wirklich offen für Ratschläge und Bewertungen zu diesem Thema. Ist das der gute Weg, dies zu tun?

Hoffe das kann einigen Leuten helfen!


18
Nun, wenn Sie eine Frage schreiben, gibt es eine Option "Beantworten Sie Ihre eigene Frage, teilen Sie Wissen Q & A-Stil", also dachte ich, wir können so teilen, sorry, wenn ich falsch liege :)
Jérémy Dutheil

4
Als Vorschlag halte ich es für eine überlegene Methode, die Antwort auf diese Frage hier aufzunehmen. Stackoverflow.com/questions/5818312/mysql-with-node-js . Vermeiden Sie Ajax-Aufrufe und passen Sie den Code besser an die Verwendung von Node an. Jetzt kann PHP einfach die Informationen aus der Datenbank auswählen.
Blackmambo

1
Ist es möglich, mit io.connect eine Verbindung zur Knoten-App herzustellen, wenn sich diese auf einem anderen Computer als Ihrer Haupt-App befindet, anstatt dass sich die Knoten-App auf demselben Server befindet, aber einen anderen Port verwendet?
Maembe

1
erfordern eine hmac-Signatur als Nachrichtenauthentifizierung. Dies stellt sicher, dass nur PHP Nachrichten an den Socket senden kann. Der Socket überprüft das signierte Token. Wenn es erfolgreich ist, sendet ti die Nachricht. Dies ist gut, um Spam zu verhindern und die Datenintegrität sicherzustellen. Posten Sie also niemals direkt vom Client auf den Node Socket. Posten Sie stattdessen mit Ajax in der PHP-App und leiten Sie diese an den Socket-Server weiter. Es ist nicht trivial, eine Socket-Verbindung zu einem Websocket-Server mit fopen + fwrite oder Stream-Auswahl aus PHP herzustellen.
r3wt

1
Mit @Bangash einverstanden, können Sie Node.js verwenden, um die Daten in der
MySQL-Datenbank

2

Ich habe eine andere Lösung, die für mich recht gut funktioniert, aber ich möchte, dass jemand kommentiert, wie effektiv sie ist, da ich (noch) nicht die Gelegenheit / Zeit hatte, sie auf dem realen Server zu testen.

Hier geht der Node-Js-Code. Ich habe diesen Code in eine Datei namens nodeServer.js eingefügt:

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);  

Und hier ist der einfache Code in PHP, der den node-js-Server mit Hilfe von file_get_contents () aufruft:

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

Funktioniert hervorragend, wenn ich die PHP-Seite lade, ruft sie wiederum die Seite nodeServer.js auf, die das Knall-Objekt jsonifiziert.

Ich habe zwei localhost-Installationen unter iis unter Windows 10, einen Standard-PHP-Server, und der nodejs-Server arbeitet mit dem ordentlichen iisnode Paket.

Der "echte" Server wird unter Ubuntu ausgeführt.

Ich denke, dies ist eine ordentliche und einfache Lösung für die Kommunikation zwischen zwei Servern, aber vielleicht hat jemand Kommentare dazu?


Dies macht für mich keinen Sinn, da Sie den Knotenserver über das PHP-Skript starten. Ich kann mir keinen Anwendungsfall dafür vorstellen. Was wir brauchen, ist eine Möglichkeit, zwischen einer laufenden node.js-Instanz und PHP zu kommunizieren.
Lorenz Meyer

Nein @Lorenz, das ist das Skript node.js, das auf einem eigenen Server ausgeführt wird. Ich rufe die node.js-Seite direkt von PHP mit file_get_contents () von einem anderen PHP-Server auf. Es ist jetzt im täglichen Gebrauch mit mehr als 500 Benutzern pro Tag. Vielleicht sind Sie verwirrt, weil das Stück "localhost: 3002"? Dies liegt daran, dass dieses Beispiel auf meinem lokalen Windows-Computer mit zwei eigenständigen Servern in iis ausgeführt wird.
Snorvarg

Ich bin wirklich verwirrt. Dies bedeutet, dass nodejs.jses sich eigentlich nicht um eine Quelldatei handelt, sondern um eine URL, die Sie so benannt haben, weil sie json enthält. Das erste würde keinen Sinn ergeben, aber das letztere scheint mir sehr verwirrend.
Lorenz Meyer

@Lorenz, ich habe versucht, das Beispiel zu verdeutlichen, indem ich den Dateinamen der Datei nodejs js geändert und den Text ein wenig bearbeitet habe. Um Ihre Frage zu beantworten, wird die jetzt in nodeServer.js umbenannte Datei auf einem eigenen Server ausgeführt. Der Aufruf von http.createServer () erstellt einen Server, der auf eingehende Verbindungen an Port 80 wartet.
wartet

Beachten Sie, dass Sie den node.js-Server direkt von einem Browser aus aufrufen können, indem Sie einfach die URL " localhost: 3002 / nodeServer.js " eingeben " , und Sie eine json-Antwort erhalten. Die Datei_get_contents () in der PHP-Datei ruft den Inhalt von einem anderen Server ab, in diesem Fall vom Server node.js.
Snorvarg

0

Versuchen Sie es ähnlich oder Sie können in meinem Blog nach dem vollständigen Beispielcode für nodejs suchen


Auf Ihrer Seite:

  • Ladebuchse JS

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

  • Objekt aus der Steckdose machen

var socket = io ();

  • Verwenden Sie die emitFunktion, um Daten an den Knotenserver zu senden.

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

Jetzt sieht Ihr Code also so aus

<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");
    });

  });
});

Erstellen Sie jetzt auf der Knotenserverseite einen Handler für Ihre Anfrage, um Ihre Anfrage zu erhalten, und senden Sie eine Nachricht an alle verbundenen Geräte / Browser (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');
});

Jetzt erstellt die Client- / Browser- / Client-Seite einen Empfänger zum Empfangen von Socket-Nachrichten vom Knotenserver

<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;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.