Skip to content

Instantly share code, notes, and snippets.

@codyphobe
Last active August 29, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codyphobe/c66866b49703511cab99 to your computer and use it in GitHub Desktop.
Save codyphobe/c66866b49703511cab99 to your computer and use it in GitHub Desktop.
Laravel & Websockets
"textalk/websocket": "1.0.*",
"cboden/ratchet": "0.3.*"
<?php namespace App\Services;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Websocket implements MessageComponentInterface {
private $clients = array();
private $connections = array();
private $topics = array();
public function onOpen(ConnectionInterface $conn) {
$this->connections[] = $conn;
echo "New connection! ({$conn->resourceId})\n";
}
public function onMessage(ConnectionInterface $from, $msg) {
$msg = json_decode($msg, true);
switch($msg['channel']){
case 'auth':
$user = Jwt::decode($msg['token']);
if(!array_key_exists($user->id, $this->clients)) {
$this->clients[$user->id] = $from;
}
break;
case 'toast':
if(array_key_exists($msg['id'], $this->clients)) {
$this->clients[$msg['id']]->send(json_encode(array('channel' => 'toast', 'message' => $msg['message'])));
}
break;
case 'broadcast':
foreach($this->connections as $conn){
if($conn != $from) {
$conn->send(json_encode(array('channel' => 'toast', 'message' => $msg['message'])));
}
}
break;
case 'subscribe':
$this->onSubscribe($msg['id'], $msg['topic']);
break;
case 'unsubscribe':
$this->onUnSubscribe($from, $msg['topic']);
break;
case 'publish':
foreach($this->topics[$msg['topic']] as $id){
$conn = $this->clients[$id];
if($conn != $from) {
$conn->send(json_encode(array('channel' => $msg['topic'], 'message' => $msg['message'])));
}
}
break;
}
}
private function onSubscribe($id, $topic){
if(!is_array($this->topics[$topic])){
$this->topics[$topic] = array();
}
$this->topics[$topic][] = $id;
}
private function onUnSubscribe(ConnectionInterface $conn, $topic = ''){
if(false !== $id = array_search($conn, $this->clients)) {
if($topic != '') {
$this->removeFromTopic($topic, $id, $this->topics[$topic]);
} else {
foreach($this->topics as $topic => $array) {
$this->removeFromTopic($topic, $id, $array);
}
}
}
}
private function removeFromTopic($topic, $id, $array){
if(false !== $key = array_search($id, $array)) {
unset($this->topics[$topic][$key]);
if(empty($this->topics[$topic])){
unset($this->topics[$topic]);
}
}
}
public function onClose(ConnectionInterface $conn) {
$this->onUnSubscribe($conn);
$this->removeConn($conn);
echo "Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
private function removeConn(ConnectionInterface $conn){
if(false !== $key = array_search($conn, $this->clients)){
unset($this->clients[$key]);
}
}
}
<?php namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
class Websocket extends Command {
/**
* The console command name.
*
* @var string
*/
protected $name = 'websocket';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function fire()
{
$server = IoServer::factory(
new HttpServer(
new WsServer(
new \App\Services\Websocket()
)
),
env('SOCKET_PORT')
);
$server->run();
$this->info('Websocket is running on port 8080');
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return [];
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return [];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment