1

My application works this way :

  1. The user logins to the website
  2. JavaScript connect to the Socket.IO server, and transmit PHPSESSID
  3. Socket.IO use PHPSESSID to connect to database and then get user_id
  4. With user_id we connect one more time to database to get user_place
  5. The user is then connected to the room user_place and can talk with other people here

The thing is that user_place can changes via, for example, another php script.

So when it changes, I need to tell the current socket io connection to fetch new “user_place” from database, so it can leave the current room and connect to the new one.

How can I achieve this ?

I had 2 guesses :

  1. When the php script is executed, connect to the existing Socket.IO connection and execute code like client.on('update_place'), function() {}. The thing is that I don't know how to connect to an existing connection (is it possible ?)
  2. Has a setTimeout() function checking constatly on the database if “user_place” has changed or not (but perfs will be terrible)

Here is some simplified code of the node server :

io.sockets.on('connection', function(client) {

    var user_place;

    // Read client cookies
    if(client.handshake.headers['cookie']) {
        var cookies = cookie.parse(client.handshake.headers['cookie']);
    }

    // If cookies exist, connect to database and get “user_place”
    if(cookies) {
        connection.query("SELECT session_value, session_time FROM sessions WHERE session_id = ?", [cookies.PHPSESSID], function(err, rows, fields) {
            if(rows[0]) {
                var session_value_json = JSON.parse(atob(rows[0].session_value));
                user_id = session_value.user_id;

                if(user_id) {
                    connection.query( "SELECT place FROM users WHERE id = ?", [user_id], function(err, rows, fields) {

                        // Set data user_place
                        user_place = rows[0].user_place;

                        // Join the room
                        client.join(user_place);
                    });
                }
            }
        });
    }

    // Chatting...
    client.on('message', function (data) {
        io.sockets.in(user_place).emit('message', {     
            user_id         : user_id,
            message_content : data.message
            } 
        );  
    });
});
lepix
  • 4,992
  • 6
  • 40
  • 53

1 Answers1

1

I doubt you can connect to Socket.IO from PHP, but you can go another way.

First, create an object that will store relationship between user IDs and socket IDs:

var userSocketIds = {};
io.sockets.on('connection', function(client) {
    ...
        connection.query( "SELECT place FROM users WHERE id = ?", [user_id], function(err, rows, fields) {

            // Set data user_place
            user_place = rows[0].user_place;

            // Join the room
            client.join(user_place);

            userSocketIds[user_id] = client.id;
            client.on('disconnect', function() {
                delete userSocketIds[user_id];  //collect garbage
            });
        });
    ...
});

Thus, if you know user ID you can get Socket.IO client ID like this:

var clientId = userSocketIds[user_id];

And then, when user_place is changed, send POST request to node (for example, to http://127.0.0.1:1337/change_user_place) and pass user_id and new_place parameters to it.

On the node side you can handle such requests with Express and change a user's room:

app.post('/change_user_place', function(req, res) {
    var clientId = userSocketIds[req.body.user_id];
    if (clientId && io.sockets.connected[clientId]) {
        io.sockets.connected[clientId].join(req.body.new_place);  //join user to new_place
    }
});

Of course, you can also send GET request instead of POST (and it would be easier to implement -- you don't need to install body-parser middleware), but with actions that change something on the server side it's better you use POST method. Check this.

You also may (and should) implement something like password authorization. It's easy: your PHP script just has to pass some password along with user ID and new place, and node should verify this password.

Good luck and sorry for my English.

Community
  • 1
  • 1
Oleg
  • 22,300
  • 9
  • 68
  • 84
  • Thank you very much for all your explanations ! It's perfect and really helped me. Just for information, I was planning to use Elephant.io (http://elephant.io/) to connect to NodeJS via PHP. But the way you did it allowed me to send data via http, and it's indeed simplier, faster and easier ! Again, thank you. – lepix Jun 23 '14 at 14:52
  • You're welcome and thank you for the link. Since I also have to combine PHP and Node.js in my work it may be useful to me :) – Oleg Jun 23 '14 at 16:33