WebSockets with PHP:
Mission Impossible
Who am I?
✔ Yoan-Alexander Grigorov
✔ Proud PHP developer
✔ Likes to screw around with OOP
So what is a WebSocket after all?
WebSocket boosts UX
✔ Forget client pulls
✔ Forget long polling
✔ Make your application event based
What google say about
WebSockets:
✔ It's easy to build WebSocket server with node.js
✔ It's hard to build WebSocket server with PHP
Research! Research! Research!
Available tools for PHP
✔ Ratchet
✔ … it's only that. Seriously, it's only Ratchet
✔ Ok, there are some other libraries, all of them
named PHPWS
Ratchet
http://socketo.me
First things first
Install with composer
Setting up a server with Ratchet
<?php
use RatchetMessageComponentInterface;
use RatchetConnectionInterface;
class Handler implements MessageComponentInterface {
public function onOpen(ConnectionInterface $conn) {}
public function onMessage(ConnectionInterface $from, $msg) {}
public function onClose(ConnectionInterface $conn) {}
public function onError(ConnectionInterface $conn, Exception $e) {}
}
Setting up a server with Ratchet
<?php
use RatchetServerIoServer;
use RatchetHttpHttpServer;
use RatchetWebSocketWsServer;
$handler = new AppHandler();
$server = IoServer::factory(
new HttpServer(new WsServer(
$handler
)
), 8123);
$server->run();
In the browser
var ws = new WebSocket('ws://127.0.0.1:8123');
// ... in some event
ws.send('Гледай кви ръки, чуек!');
// ... listener for messages:
ws.onmessage = function (message) {
alert(message);
};
Let's make a chat!
What do we need?
✔ Keep all active connection objects
✔ When a connection sends a message, notify all
others
✔ On disconnect – remove connection object from
the in-memory cache (map)
Connections handling
<?php
class Handler implements MessageComponentInterface {
private $connections = [];
public function onOpen(ConnectionInterface $conn) {
$this->connections[$conn->resourceId] = $conn;
}
public function onMessage(ConnectionInterface $from, $msg) {
foreach ($this->connections as $receiver) {
$receiver->send($msg);
}
}
public function onClose(ConnectionInterface $conn) {
unset($this->connections[$conn->resourceId]);
}
}
That's it!
Keep an eye on:
✔ Run it like a daemon (/etc/init.d/skeleton)
✔ Fatal errors and exceptions – they kill the
daemon
✔ ORMs like Doctrine help you a lot
Doctrine uses Identity Map
Identity map gives you wings!
Web Servers and Web Sockets
Don't forget good old Ajax!
But how ajax could send messages
to the WebSocket server?
Message Queues
ZeroMQ
✔ Libzmq
✔ Has a PHP extension in PECL
✔ React/ZMQ (PHP wrapper)
✔ "react/zmq": "0.2.*|0.3.*" in Composer
What you need to know
✔ There are ZeroMQ listeners
– They use simple TCP
✔ There are ZeroMQ contexts (senders)
– They connect to ZeroMQ listeners and send
messages
What you need to know
✔ You need ZeroMQ listener in the WebSocket
daemon
✔ Ordinary PHP scripts send messages to the
listener
✔ Since ZeroMQ is in the WebSocket daemon, it
could easily interact with WebSocket
connections
Let's add ZeroMQ to our application!
Add callback for ZeroMQ messages
<?php
class Handler implements MessageComponentInterface
{
// ...
// this is CUSTOM method (not from interface)
public function onZMQMessage($message)
{
}
}
Add ZeroMQ listener to the daemon
<?php
use ...
$handler = new AppHandler();
$server = IoServer::factory(
new HttpServer(new WsServer(
$handler
)
), 8123);
// Listen on 127.0.0.1:4444
$context = new ReactZMQContext($server->loop);
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind("tcp://127.0.0.1:4444");
$pull->on('message', function ($data) use ($handler) {
$handler->onZMQMessage($data);
});
$server->run();
In your Ajax server script
<?php
// ... add stuff to the database, other things...
// notify using ZeroMQ:
$context = new ZMQContext();
$socket = $context->getSocket(ZMQ::SOCKET_PUSH, 'pusher');
$socket->connect("tcp://127.0.0.1:4444");
$socket->send('Глей кви ръки! Туй аз ли съм!?');
Go! Try it yourself!
Working code examples from this talk:
https://github.com/sasquatch-mc/ratchet-example
(check the branches)
References
✔ http://socketo.me
✔ http://zeromq.org
Thanks and good luck!
✔ joan.grigorov@gmail.com
✔ bgscripts.com

WebSockets with PHP: Mission impossible

  • 1.
  • 2.
    Who am I? ✔Yoan-Alexander Grigorov ✔ Proud PHP developer ✔ Likes to screw around with OOP
  • 3.
    So what isa WebSocket after all?
  • 5.
    WebSocket boosts UX ✔Forget client pulls ✔ Forget long polling ✔ Make your application event based
  • 6.
    What google sayabout WebSockets: ✔ It's easy to build WebSocket server with node.js ✔ It's hard to build WebSocket server with PHP
  • 7.
  • 8.
    Available tools forPHP ✔ Ratchet ✔ … it's only that. Seriously, it's only Ratchet ✔ Ok, there are some other libraries, all of them named PHPWS
  • 9.
  • 10.
  • 11.
  • 12.
    Setting up aserver with Ratchet <?php use RatchetMessageComponentInterface; use RatchetConnectionInterface; class Handler implements MessageComponentInterface { public function onOpen(ConnectionInterface $conn) {} public function onMessage(ConnectionInterface $from, $msg) {} public function onClose(ConnectionInterface $conn) {} public function onError(ConnectionInterface $conn, Exception $e) {} }
  • 13.
    Setting up aserver with Ratchet <?php use RatchetServerIoServer; use RatchetHttpHttpServer; use RatchetWebSocketWsServer; $handler = new AppHandler(); $server = IoServer::factory( new HttpServer(new WsServer( $handler ) ), 8123); $server->run();
  • 14.
    In the browser varws = new WebSocket('ws://127.0.0.1:8123'); // ... in some event ws.send('Гледай кви ръки, чуек!'); // ... listener for messages: ws.onmessage = function (message) { alert(message); };
  • 15.
  • 16.
    What do weneed? ✔ Keep all active connection objects ✔ When a connection sends a message, notify all others ✔ On disconnect – remove connection object from the in-memory cache (map)
  • 17.
    Connections handling <?php class Handlerimplements MessageComponentInterface { private $connections = []; public function onOpen(ConnectionInterface $conn) { $this->connections[$conn->resourceId] = $conn; } public function onMessage(ConnectionInterface $from, $msg) { foreach ($this->connections as $receiver) { $receiver->send($msg); } } public function onClose(ConnectionInterface $conn) { unset($this->connections[$conn->resourceId]); } }
  • 18.
  • 19.
    Keep an eyeon: ✔ Run it like a daemon (/etc/init.d/skeleton) ✔ Fatal errors and exceptions – they kill the daemon ✔ ORMs like Doctrine help you a lot
  • 20.
  • 22.
  • 23.
    Web Servers andWeb Sockets
  • 24.
  • 25.
    But how ajaxcould send messages to the WebSocket server?
  • 26.
  • 28.
    ZeroMQ ✔ Libzmq ✔ Hasa PHP extension in PECL ✔ React/ZMQ (PHP wrapper) ✔ "react/zmq": "0.2.*|0.3.*" in Composer
  • 29.
    What you needto know ✔ There are ZeroMQ listeners – They use simple TCP ✔ There are ZeroMQ contexts (senders) – They connect to ZeroMQ listeners and send messages
  • 30.
    What you needto know ✔ You need ZeroMQ listener in the WebSocket daemon ✔ Ordinary PHP scripts send messages to the listener ✔ Since ZeroMQ is in the WebSocket daemon, it could easily interact with WebSocket connections
  • 31.
    Let's add ZeroMQto our application!
  • 32.
    Add callback forZeroMQ messages <?php class Handler implements MessageComponentInterface { // ... // this is CUSTOM method (not from interface) public function onZMQMessage($message) { } }
  • 33.
    Add ZeroMQ listenerto the daemon <?php use ... $handler = new AppHandler(); $server = IoServer::factory( new HttpServer(new WsServer( $handler ) ), 8123); // Listen on 127.0.0.1:4444 $context = new ReactZMQContext($server->loop); $pull = $context->getSocket(ZMQ::SOCKET_PULL); $pull->bind("tcp://127.0.0.1:4444"); $pull->on('message', function ($data) use ($handler) { $handler->onZMQMessage($data); }); $server->run();
  • 34.
    In your Ajaxserver script <?php // ... add stuff to the database, other things... // notify using ZeroMQ: $context = new ZMQContext(); $socket = $context->getSocket(ZMQ::SOCKET_PUSH, 'pusher'); $socket->connect("tcp://127.0.0.1:4444"); $socket->send('Глей кви ръки! Туй аз ли съм!?');
  • 35.
    Go! Try ityourself!
  • 36.
    Working code examplesfrom this talk: https://github.com/sasquatch-mc/ratchet-example (check the branches)
  • 37.
  • 38.
    Thanks and goodluck! ✔ joan.grigorov@gmail.com ✔ bgscripts.com