nodeJS + Socket.IOとPHPを統合する方法


98

nodeJSとPHPの間で通信するための良い方法を見つけるために、私は最近周りを見回しています。ここにアイデアがあります:nodeJSはまだかなり新しく、それだけで完全なアプリケーションを開発するのはちょっと難しいかもしれません。さらに、リアルタイム通知、チャットなど、プロジェクトの1つのモジュールでのみ必要になる場合があります。他のすべてのものをPHPで管理したい場合は、おそらくより簡単です(そして、 CodeIgniterやSymfonyなどの既存のフレームワーク)。

簡単な解決策が欲しいです。ApacheとNodeサーバー間の通信にcURLまたは3番目のサーバーを使用したくありません。私が欲しいのは、クライアント側の単純なJavascriptでノードからイベントをキャッチできるようにすることです。

完全な場合、ほとんどの場合クライアント側がノードサーバーによって実行されていたため、私の場合には該当しないという答えは見つかりませんでした。だから私はすべての可能なトピックをクロールし、最後に私の答えを見つけました。私はこれを共有し、それがすべて明確であるようにしたいと思います。

これが一部の人々に役立つことを願っています!;)

回答:


131

したがって、最初に、完全なコードにアクセスする場合は、プロジェクトをgithubに配置します。https//github.com/jdutheil/nodePHP

これは非常にシンプルなサンプルプロジェクトです。Webチャットです。あなたは作者とメッセージを持っているだけで、送信を押すとそれがmysqlデータベースに保存されます。アイデアは、リアルタイムの更新を送信し、実際の会話をすることです。;)そのためにnodeJSを使用します。

ここではPHPコードについては触れません。これは非常に単純で、ここでは面白くありません。私がお見せしたいのは、nodeJSコードを統合する方法です。

私はexpressとSocket.IOを使用しているので、npmでこれらのモジュールをインストールしてください。次に、単純な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 );

新しいユーザーが接続されたときにイベントコールバックを登録しました。メッセージ(チャットメッセージを表す)を受信するたびに、接続しているすべてのユーザーにブロードキャストします。今、トリッキーな部分:クライアント側!ほとんどの時間を要したのは、nodeServerなしでSocket.IOコードを実行できるスクリプトが含まれていないためです(クライアントページはApacheによって提供されるため)。

しかし、すべてはすでに行われています。npmでSocket.IOモジュールをインストールすると、スクリプトがで利用可能になり/node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.jsます。私の場合、PHPページにスクリプトを含めます。

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

最後に、ノードサーバーに接続し、イベントがページを更新するのを待つ、nodeClient.jsを作成します。;)

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

私はできるだけ早くコードを更新して改善するように努めますが、それはすでにすべてのクールなことに開かれていると思います!私はこのことについてのアドバイスとレビューを本当に開いています、それはそれを行う良い方法ですか?

これが一部の人々に役立つことを願っています!


18
あなたが質問を書くとき、私たちはこのように共有することができ、私は思ったので、まあ、オプション「あなた自身の質問に答える、共有知識Q&スタイル」には、申し訳ありません私は:)間違っている場合は、そこにある
ジェレミーDutheil

4
提案として、この質問への回答をここに組み込むのは、stackoverflow.com / questions / 5818312 / mysql-with-node-jsが優れた方法だと思います。ajax呼び出しを回避し、nodeの使用によりコードをインライン化します。これで、PHPはデータベースから情報を選択するだけです。
blackmambo 2013年

1
同じサーバー上にあるが異なるポートを使用するノードアプリではなく、メインアプリとは異なるマシン上にある場合、io.connectを使用してノードアプリに接続することは可能ですか?
maembe 14

1
メッセージ認証としてhmac署名が必要です。これにより、phpのみがソケットにメッセージをブロードキャストできることが保証されます。ソケットは署名されたトークンを検査し、通過した場合、tiはメッセージをブロードキャストします。これはスパムを防ぎ、データの整合性を確保するのに役立ちます。したがって、クライアントからノードソケットに直接投稿しないでください。代わりに、ajaxを使用してphpアプリに投稿し、それをソケットサーバーに中継します。fopen + fwriteまたはphpからのストリーム選択を使用してWebsocketサーバーへのソケット接続を開くことは、かなり簡単ではありません。
r3wt 2015年

1
@Bangashに同意します。Node.jsを使用して、PHPの代わりにmysql dbにデータを保存できます。これにより、処理速度が
大幅に向上し

2

私にとって非常にうまく機能する別のソリューションがありますが、実際のサーバーでテストする機会/時間はまだないので、誰かがそれがどれほど効果的であるかについてコメントしてほしいです。

ここにnode-jsコードがあります。このコードを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);  

そして、これがphpの簡単なコードで、file_get_contents()の助けを借りてnode-jsサーバーを呼び出しています:

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

php-pageをロードすると、knall-objectをjsonifyするnodeserver.jsページが呼び出されます。

Windows 10のiisで2つのlocalhost-installationsを実行しています。1つは標準のphp-serverで、nodejs-serverはきちんとしたiisnodeパッケージで動作します。

「実際の」サーバーはubuntuで実行されます。

これは2つのサーバー間の通信のためのきちんとした簡単な解決策だと思いますが、多分誰かがそれについて何かコメントがありますか?


これは、phpスクリプト内からノードサーバーを起動しているため、私には意味がありません。この使用例を想像することはできません。必要なのは、実行中のnode.jsインスタンスとphpの間の通信方法です。
Lorenz Meyer

@Lorenzはありません。それは、独自のサーバーで実行されているnode.jsスクリプトです。別のphpサーバーからfile_get_contents()を使用して、phpから直接node.js-pageを呼び出しています。現在、毎日500人以上のユーザーが使用しています。「localhost:3002」の部分が原因で混乱しているのではないでしょうか。これは、この例がiisに2つのスタンドアロンサーバーを備えたローカルのWindowsコンピューターで実行されるためです。
Snorvarg 2017年

私は本当に混乱しています。つまり、これnodejs.jsは実際にソースファイルではありませんが、jsonが含まれているため、指定したURLです。前者は意味がありませんが、後者は私を非常に混乱させるようです。
Lorenz Meyer

@ Lorenz、nodejs jsファイルのファイル名を変更して例を明確にし、テキストを少し編集してみました。質問に答えるために、nodeserver.jsに名前が変更されたファイルは、独自のサーバーで実行されます。http.createServer()の呼び出しは、サーバーを作成します(聞いた)80番ポートでの着信接続のためだ
Snorvarg

url " localhost:3002 / nodeserver.js "を入力するだけで、ブラウザーから直接node.jsサーバーを呼び出すことができ、json-responseを取得することに注意してください。phpファイルのfile_get_contents()は、別のサーバー(この場合はnode.jsサーバー)からコンテンツをフェッチします。
Snorvarg 2017年

0

同様に試すか、私のブログでnodejsの完全なサンプルコードを確認できます


ページ側:

  • ソケットJSをロード

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

  • ソケットのオブジェクトを作る

var socket = io();

  • emit関数を使用してデータをノードサーバーに送信します。

socket.emit( 'new_notification'、{
メッセージ: 'メッセージ'、
タイトル: 'タイトル'、
アイコン: 'アイコン'、
});

だから今あなたのコードは次のようになります

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

  });
});

Nodeサーバー側で、リクエストのハンドラーを作成してリクエストを取得し、接続されているすべてのデバイス/ブラウザー(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');
});

クライアント/ブラウザ/クライアント側は、ノードサーバーからソケットメッセージを受信するレシーバを作成します。

<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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.