156

Is it possible to use Sockets.io on the client side and communicate with a PHP based application on the server? Does PHP even support such a 'long-lived connection' way of writing code?

All the sample code I find for socket.io seems to be for node.js on the server side, so no help there.

3
  • 3
    Possible duplicate: Socket.io from php source Commented Jun 18, 2011 at 22:05
  • You may want to consider just pusher. It has a nifty PHP library that I'll be using. Commented Oct 30, 2011 at 20:36
  • 1
    hi, try this one - github.com/walkor/phpsocket.io Commented Jul 10, 2017 at 7:40

13 Answers 13

108

It may be a little late for this question to be answered, but here is what I found.

I don't want to debate on the fact that nodes does that better than php or not, this is not the point.

The solution is : I haven't found any implementation of socket.io for PHP.

But there are some ways to implement WebSockets. There is this jQuery plugin allowing you to use Websockets while gracefully degrading for non-supporting browsers. On the PHP side, there is this class which seems to be the most widely used for PHP WS servers.

Sign up to request clarification or add additional context in comments.

1 Comment

the phpwebsocket class is indeed the way to go if you want a php websocket server implementation. However this is not related to the question. The OP already has a WS server (socket.io) implemented and asked for ways to communicate with a php application.
79

If you want to use socket.io together with php this may be your answer!

project website:

elephant.io

they are also on github:

https://github.com/wisembly/elephant.io

Elephant.io provides a socket.io client fully written in PHP that should be usable everywhere in your project.

It is a light and easy to use library that aims to bring some real-time functionality to a PHP application through socket.io and websockets for actions that could not be done in full javascript.

example from the project website (communicate with websocket server through php)

php server

use ElephantIO\Client as Elephant;

$elephant = new Elephant('http://localhost:8000', 'socket.io', 1, false, true, true);

$elephant->init();
$elephant->send(
    ElephantIOClient::TYPE_EVENT,
    null,
    null,
    json_encode(array('name' => 'foo', 'args' => 'bar'))
);
$elephant->close();

echo 'tryin to send `bar` to the event `foo`';

socket io server

var io = require('socket.io').listen(8000);

io.sockets.on('connection', function (socket) {
  console.log('user connected!');

  socket.on('foo', function (data) {
    console.log('here we are in action event and data is: ' + data);
  });
});

8 Comments

I'll give you a +1 here, but it looks like this is still a little ways from being usable in a production environment.
I've seen this one, but one thing confused me. Isn't the point here to have PHP implement a sockets.io server? and, instead, Elepant.io seems to be a PHP implementation of a sockets.io client for which you can connect to some other sockets.io server (meaning, elephant.io is not listening for connections from your sockets.io clients, connecting to them and servicing them)?
Hi all. Elephant.io aim is just to fire events from PHP to a socket.io server. Not to open a persistent connexion. But to be able to quickly connect and send events / messages. We use it in production and it works like a charm.
this library is not maintained anymore and has some issues for us
Elephant is dead now. RIP
|
26

If you really want to use PHP as your backend for socket.io, here are what I found. This is two socket.io php server side alternatives.

  1. https://github.com/walkor/phpsocket.io

  2. https://github.com/RickySu/phpsocket.io

Example code for the first repository like this:

use PHPSocketIO\SocketIO;

// listen port 2021 for socket.io client
$io = new SocketIO(2021);
$io->on('connection', function($socket)use($io){
  $socket->on('chat message', function($msg)use($io){
    $io->emit('chat message', $msg);
  });
});

1 Comment

this should be the voted answer
23

UPDATE: Aug 2014 The current socket.io v1.0 site has a PHP example:- https://github.com/rase-/socket.io-php-emitter

Comments

15

I know the struggle man! But I recently had it pretty much working with Workerman. If you have not stumbled upon this php framework then you better check this out!

Well, Workerman is an asynchronous event driven PHP framework for easily building fast, scalable network applications. (I just copied and pasted that from their website hahahah http://www.workerman.net/en/)

The easy way to explain this is that when it comes web socket programming all you really need to have is to have 2 files in your server or local server (wherever you are working at).

  1. server.php (source code which will respond to all the client's request)

  2. client.php/client.html (source code which will do the requesting stuffs)

So basically, you right the code first on you server.php and start the server. Normally, as I am using windows which adds more of the struggle, I run the server through this command --> php server.php start

Well if you are using xampp. Here's one way to do it. Go to wherever you want to put your files. In our case, we're going to the put the files in

C:/xampp/htdocs/websocket/server.php

C:/xampp/htdocs/websocket/client.php or client.html

Assuming that you already have those files in your local server. Open your Git Bash or Command Line or Terminal or whichever you are using and download the php libraries here.

https://github.com/walkor/Workerman

https://github.com/walkor/phpsocket.io

I usually download it via composer and just autoload those files in my php scripts.

And also check this one. This is really important! You need this javascript libary in order for you client.php or client.html to communicate with the server.php when you run it.

https://github.com/walkor/phpsocket.io/tree/master/examples/chat/public/socket.io-client

I just copy and pasted that socket.io-client folder on the same level as my server.php and my client.php

Here is the server.php sourcecode

<?php
require __DIR__ . '/vendor/autoload.php';

use Workerman\Worker;
use PHPSocketIO\SocketIO;

// listen port 2021 for socket.io client
$io = new SocketIO(2021);
$io->on('connection', function($socket)use($io){
    $socket->on('send message', function($msg)use($io){
        $io->emit('new message', $msg);
    });
});

Worker::runAll();

And here is the client.php or client.html sourcecode

<!DOCTYPE html>
<html>
    <head>
        <title>Chat</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">        
    </head>
    <body>
        <div id="chat-messages" style="overflow-y: scroll; height: 100px; "></div>        
        <input type="text" class="message">
    </body>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>    
    <script src="socket.io-client/socket.io.js"></script>  
    <script>
            var socket = io.connect("ws://127.0.0.1:2021");

            $('.message').on('change', function(){
                socket.emit('send message', $(this).val());
                $(this).val('');
            });

            socket.on('new message', function(data){
                $('#chat-messages').append('<p>' + data +'</p>');
            });
    </script>
</html>

Once again, open your command line or git bash or terminal where you put your server.php file. So in our case, that is C:/xampp/htdocs/websocket/ and typed in php server.php start and press enter.

Then go to you browser and type http://localhost/websocket/client.php to visit your site. Then just type anything to that textbox and you will see a basic php websocket on the go!

You just need to remember. In web socket programming, it just needs a server and a client. Run the server code first and the open the client code. And there you have it! Hope this helps!

1 Comment

indeed, this website must find a way to get rid of obsolete old answers
7

For 'long-lived connection' you mentioned, you can use Ratchet for PHP. It's a library built based on Stream Socket functions that PHP has supported since PHP 5.

For client side, you need to use WebSocket that HTML5 supported instead of Socket.io (since you know, socket.io only works with node.js).

In case you still want to use Socket.io, you can try this way: - find & get socket.io.js for client to use - work with Ratchet to simulate the way socket.io does on server

Hope this helps!

1 Comment

So how do you simulate how socket.io works with Ratchet? Because if you just establish a normal connection with Ratchet, it is not recognized by a socket-io client due to missing metadata.
6

Erm, why would you want to? Leave PHP on the backend and NodeJS/Sockets to do its non-blocking thing.

Here is something to get you started: http://groups.google.com/group/socket_io/browse_thread/thread/74a76896d2b72ccc

Personally I have express running with an endpoint that is listening expressly for interaction from PHP.

For example, if I have sent a user an email, I want socket.io to display a real-time notification to the user.

Want interaction from socket.io to php, well you can just do something like this:

var http = require('http'),
            host = WWW_HOST,
            clen = 'userid=' + userid,
            site = http.createClient(80, host),
            request = site.request("POST", "/modules/nodeim/includes/signonuser.inc.php",  
                {'host':host,'Content-Length':clen.length,'Content-Type':'application/x-www-form-urlencoded'});                     

request.write('userid=' + userid);      
request.end();  

Seriously, PHP is great for doing server side stuff and let it be with the connections it has no place in this domain now. Why do anything long-polling when you have websockets or flashsockets.

11 Comments

Because some of us are only able to get a cheap host that will only let you use php and mysql.
Because some of us have to work with existing frameworks that depend on PHP. For example we develop and sell a PHP script, but would like to improve the IM by using websockets, we dont want to write all the fallbacks that socket.io already implemented but we cannot require NodeJS from our clients.
@PaulM: I tried few <$10 VPS providers, and all of those really suck. Each were very slow, when something is broken, support is horrible etc. On the other hand, in Finland it's not rare to get decent quality web hosting (but with php/mysql/static files only) with adsl subscription, without paying any extra. So no, being able to buy crappy VPS for $5 is definitely not a solution.
For <$10 VPS providers, the only decent one I've found so far is digitalocean.com. But that one is pretty good.
I don't agree. I think an answer like this is very relevant. Someone telling you "you're using it wrong" could be worth a lot more than someone helping you to use it wrong.
|
4

If you really want to use PHP as your backend for WebSockets, these links can get you on your way:

https://github.com/lemmingzshadow/php-websocket

http://www.htmlgoodies.com/html5/other/create-a-bi-directional-connection-to-a-php-server-using-html5-websockets.html#fbid=QqpDVi8FqD9

1 Comment

Do these allow you to use socket.io (with all its supported transports and browsers). Or do you have to use the client that comes with php-websocket?
4

How about this ? PHPSocketio ?? It is a socket.io php server side alternative. The event loop is based on pecl event extension. Though haven't tried it myself till now.

Comments

2

I haven't tried it yet, but you should be able to do this with ReactPHP and this socket component. Looks just like Node, but in PHP.

Comments

1

I was looking for a really simple way to get PHP to send a socket.io message to clients.

This doesn't require any additional PHP libraries - it just uses sockets.

Instead of trying to connect to the websocket interface like so many other solutions, just connect to the node.js server and use .on('data') to receive the message.

Then, socket.io can forward it along to clients.

Detect a connection from your PHP server in Node.js like this:

//You might have something like this - just included to show object setup
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);

server.on("connection", function(s) {
    //If connection is from our server (localhost)
    if(s.remoteAddress == "::ffff:127.0.0.1") {
        s.on('data', function(buf) {
            var js = JSON.parse(buf);
            io.emit(js.msg,js.data); //Send the msg to socket.io clients
        });
    }
});

Here's the incredibly simple php code - I wrapped it in a function - you may come up with something better.

Note that 8080 is the port to my Node.js server - you may want to change.

function sio_message($message, $data) {
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    $result = socket_connect($socket, '127.0.0.1', 8080);
    if(!$result) {
        die('cannot connect '.socket_strerror(socket_last_error()).PHP_EOL);
    }
    $bytes = socket_write($socket, json_encode(Array("msg" => $message, "data" => $data)));
    socket_close($socket);
}

You can use it like this:

sio_message("chat message","Hello from PHP!");

You can also send arrays which are converted to json and passed along to clients.

sio_message("DataUpdate",Array("Data1" => "something", "Data2" => "something else"));

This is a useful way to "trust" that your clients are getting legitimate messages from the server.

You can also have PHP pass along database updates without having hundreds of clients query the database.

4 Comments

Nice idea, I was looking for a way to skip redis (if that's a good idea)! There's a typo in the first code, a semicolon after s.remoteAddress;. However, I'm not getting it to work. I get the connection in node, it detects the connection, the remoteaddress is correct, but s.on('data') never happens, but nothing happens. I tried s.on('msg') too. I'm using your exact PHP code. I'm using https, for the node server, but that shouldn't matter?
@Niclas hey sorry about the typo - can't believe that was there all along. Is your node server running on port 8080? If not, you need to change the port. If so, check the Remote Address that's being returned - make sure it's the loopback/local address - it may be different with your server setup. For testing, you can remove the line if(s.remoteAddress == "::ffff:127.0.0.1")
Thanks for the quick reply! I did successfully console.log all the way, even the remoteaddress was right, it just doesn’t enter the s.on(’data’) section. Is there a way to test what message was sent? Please re-read my comment to see if I missed something. I might start this as a new question to post the code but it’s almost exactly like yours.
I started this as a new question to make it easier to discuss in detail: stackoverflow.com/questions/53689391/…
1

as far as I know you can't use socket.io with PHP. Here is the solution to your problem: Use websockets through a library called RatChet.

Here is the sample code of chat system I built using websocket:

You first need a server.php file:

<?php
require __DIR__ . '/vendor/autoload.php';
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use App\MainHandler;

include_once("database.php");
// Create WebSocket server
$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new MainHandler($conn)
        )
    ),
    8080
);

echo "WebSocket server started on ws://localhost:8080\n";
$server->run();

Then you need to create for clients to build connection with your server. In my case, it's webcoket.js:

const socket = new WebSocket(`ws://127.0.0.1:8080`);
let sender_id;
if(window.location.search !== ""){
    sender_id = window.location.search.split("sender_id")[1].substring(1);
}

// Connection opened
socket.onopen = () => {
    console.log("Connection established");
    socket.send(JSON.stringify({
        type : "establish_notifications",
        sender_id : sender_id,
    }));
    console.log('WebSocket connection established for sender_id:', sender_id);
};

// Handle errors
socket.onerror = (error) => {
    console.log('WebSocket error:', error);
};

// Handle connection close
socket.onclose = () => {
    console.log('Connection closed');
};

export default socket;

I have built two features, live chats and live notification for those chats, and in Wsserver, you cann add only handler:

const socket = new WebSocket(`ws://127.0.0.1:8080`);
let sender_id;
if(window.location.search !== ""){
    sender_id = window.location.search.split("sender_id")[1].substring(1);
}

// Connection opened
socket.onopen = () => {
    console.log("Connection established");
    socket.send(JSON.stringify({
        type : "establish_notifications",
        sender_id : sender_id,
    }));
    console.log('WebSocket connection established for sender_id:', sender_id);
};

// Handle errors
socket.onerror = (error) => {
    console.log('WebSocket error:', error);
};

// Handle connection close
socket.onclose = () => {
    console.log('Connection closed');
};

export default socket;

Here is my chat.php file:

<?php
    namespace Library;
    use Ratchet\MessageComponentInterface;
    use Ratchet\ConnectionInterface;

    class Chat implements MessageComponentInterface {
        protected $clients;
        protected $token;
        protected $dbconn;
        protected $chatTokens; // Store tokens and associated connections

        public function __construct($dbconnection) {
            $this->clients = new \SplObjectStorage;
            $this->dbconn = $dbconnection;
            $this->chatTokens = []; // Format: ['token' => [ConnectionInterface]]
        }

        public function onOpen(ConnectionInterface $wsconn) {
            $this->clients->attach($wsconn);
            echo "New connection! ({$wsconn->resourceId})\n";
        }

        public function onMessage(ConnectionInterface $wsconn, $msg) {
            $data = json_decode($msg, true);
            $sender_id = $data['sender_id'];
            $receiver_id = $data['receiver_id'];

            //GENERATE TOKEN OR GET TOKEN FROM DB

            if($data['type'] === 'token'){
                    $select = "SELECT token FROM messages 
                WHERE (sender_id = '$sender_id' AND receiver_id = '$receiver_id') 
                    OR (receiver_id = '$sender_id' AND sender_id = '$receiver_id') 
                LIMIT 1";
                    $result = mysqli_query($this->dbconn, $select);

                    if ($row = mysqli_fetch_assoc($result)) {
                        $this->token = $row['token'];
                    } else {
                        $this->token = $this->createChatToken();
                        // $this->token = $this->createChatToken();
                        // if(isset($this->chatTokens[$this->token])){
                        //     $this->chatTokens[$this->token] = [];
                        // }
                    }
                    // if(!isset($this->chatTokens[$this->token])){
                    //     $this->chatTokens[$this->token] = [];
                    // }
                    if (!isset($this->chatTokens[$this->token])) {
                        $this->chatTokens[$this->token] = [];
                    }
                    
                    // Check if the connection already exists
                    if (!in_array($wsconn, $this->chatTokens[$this->token], true)) {
                        // Add the connection only if it's not already present
                        $this->chatTokens[$this->token][] = $wsconn;
                    }
                    
                    // $this->chatTokens[$this->token][] = $wsconn;
                    // echo $this->token;
                }
                if($data['type'] === 'message' || !isset($data['type'])){
                    $message_text = $data['message_text'];
                    $insert = "INSERT INTO messages (sender_id, receiver_id, message_text, token) VALUES ('$sender_id', '$receiver_id', '$message_text', '$this->token')";

                    $mysqli_insert_query = mysqli_query($this->dbconn, $insert);
                    if($mysqli_insert_query){
                        echo "Inserted data into database";
                    }else{
                        echo "Could not insert into database";
                    }

                    // Route the message only to connections associated with the token
                    foreach ($this->chatTokens[$this->token] as $client) {
                            $client->send(json_encode([
                                    'token' => $this->token,
                                    'type' => 'message',
                                    'sender_id' => $sender_id,
                                    'receiver_id' => $receiver_id,
                                    'message_text' => $message_text
                                    ]));
                            // echo "Data {$message_text} sent to {$receiver_id}";
                    }
                }   
        }

        public function onClose(ConnectionInterface $wsconn) {
            // Detach connection
            $this->clients->detach($wsconn);
            foreach($this->chatTokens as $token => &$connections){
                foreach($connections as $index => $connection){
                    if($connection === $wsconn){
                        unset($connections[$index]);
                    }
                }
            }
            echo "Connection {$wsconn->resourceId} has disconnected\n";
        }

        public function onError(ConnectionInterface $wsconn, \Exception $e) {
            echo "An error has occurred: {$e->getMessage()}\n";
            $wsconn->close();
        }

        // Generate a unique token for a new chat session
        public function createChatToken() {
            $tok = bin2hex(random_bytes(16)); // Generate a secure random token
            return $tok;
        }
    }
?>

Here is my notification.php file:

<?php
    namespace Library;
    use Ratchet\MessageComponentInterface;
    use Ratchet\ConnectionInterface;
    include_once("send_email.php");

    class Notification implements MessageComponentInterface{
        protected $clients;
        protected $NotificationToken;
        protected $dbconn;

        public function __construct($dbconnection){
            $this->dbconn = $dbconnection;
            $this->clients = [];
        }

        public function onOpen(ConnectionInterface $wsconn){
            //EXTRACTED THE RECEIVER ID FROM URL
            // $query = $wsconn->httpRequest->getUri()->getQuery();
            // parse_str($query, $queryParams);
            // $sender_id = $queryParams['sender_id']??null;
            // $receiver_id = $queryParams['receiver_id']??null;

            //SET THE CONNECTION IN CLIENTS
            // if($sender_id && $receiver_id){
            //     $key = $sender_id.'_'.$receiver_id;
            //     $this->clients[$key] = []; 
            // }
            // $this->clients[$key][] = $wsconn;
            echo "Notification opened";
        }

        public function onMessage(ConnectionInterface $wsconn, $msg){
            $data = json_decode($msg, true);
            echo "Message data received! {$data['type']}";
            if($data['type'] === 'establish_notifications'){
                $sender_id = $data['sender_id'];
                // if(!isset($this->clients[$sender_id])){
                //     $this->clients[$sender_id] = null;
                // }
                $this->clients[$sender_id] = $wsconn;
                $wsconn->send(json_encode([
                    'type' => 'notification_established',
                    'message_text' => 'Notifications established for the sender'
                ]));
                echo "Sender notification ID created!";
            }
            // $receiver_id = $data['receiver_id'];
            // $sender_id = $data['sender_id'];
            // $key = $receiver_id.'_'.$sender_id;
            // $sender_receiver_key = $sender_id.'_'.$receiver_id;
            // if(isset($this->clients[$sender_receiver_key])){
            //     $this->clients[$sender_receiver_key] = [];
            // }
            // $this->clients[$sender_receiver_key][] = $wsconn;
            // $receiver_sender_key = $receiver_id.'_'.$sender_id;
            
            if($data['type'] === 'notification'){
                $receiver_id = $data['receiver_id'];
                $sender_id = $data['sender_id'];
                $message_text = $data['message_text'];
                // if(isset($this->clients[$key])){
                // if(isset($this->clients[$receiver_sender_key])){
                //     // foreach($this->clients[$key] as $client){
                //     foreach($this->clients[$receiver_sender_key] as $client){
                //         $client->send(json_encode([
                //             'type' => 'notification',
                //             'sender_id' => $sender_id,
                //             'receiver_id' => $receiver_id,
                //             'message_text' => $message_text
                //         ]));
                //         // echo "Notification: {$message_text}";
                //     }
                // }
                if(isset($this->clients[$receiver_id])){
                    // foreach($this->clients[$key] as $client){
                    // foreach($this->clients as $key => $client){
                    //     if($key === $receiver_id){
                    $client =$this->clients[$receiver_id];
                            $client->send(json_encode([
                                'type' => 'notification',
                                'sender_id' => $sender_id,
                                'receiver_id' => $receiver_id,
                                'message_text' => $message_text
                            ]));

                            //SELECT RECEIVER EMAIL FROM DB
                            $select = "SELECT email, full_name FROM users WHERE id = '$receiver_id'";
                            $mysqli_select_query = mysqli_query($this->dbconn, $select);
                            while($rows = mysqli_fetch_assoc($mysqli_select_query)){
                                $receiver_email = $rows['email'];
                                $receiver_full_name = $rows['full_name'];
                            }

                            $send_email = send_email("{$receiver_email}", "{$receiver_full_name}", "New Message Received", $message_text);
                            if($send_email){
                                echo "Email sent!";
                            }else{
                                echo "Could not send email!";
                            }
                    //     }
                    //     // echo "Notification: {$message_text}";
                    // }
                }else{
                    echo "Receiver ID not found!";
                }
            }
        }

        public function onClose(ConnectionInterface $wsconn){
            foreach ($this->clients as $id => $client) {
                if ($client === $wsconn) {
                    // $this->clients[$id] = null;
                }
            }            
        }

        public function onError(ConnectionInterface $wsconn, \Exception $e){
            echo "onError: {$e->getMessage()}";
        }
    }
?>

Comments

0

Look in this libraryes for php http://phptrends.com/category/70. Or use native from php http://www.php.net/manual/en/book.sockets.php .

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.