Created
March 14, 2017 10:40
-
-
Save Mevrael/6855dd47d45fa34ee7161c8e0d2d0e88 to your computer and use it in GitHub Desktop.
Laravel + WebSocket (Ratchet/ReactPHP) integration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// add this to web routes | |
Route::get('/websocket/open', 'WebSocketController@onOpen'); | |
Route::get('/websocket/message', 'WebSocketController@onMessage'); | |
Route::get('/websocket/close', 'WebSocketController@onClose'); | |
Route::get('/websocket/error', 'WebSocketController@onError'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers; | |
use Illuminate\Http\Request; | |
use Illuminate\Support\Facades\Auth; | |
use Illuminate\Support\Facades\Cookie; | |
use Illuminate\Support\Facades\Mail; | |
use Illuminate\Support\Facades\Session; | |
use Ratchet\WebSocket\Version\RFC6455\Connection; | |
class WebSocketController | |
{ | |
/** | |
* @var Connection | |
*/ | |
protected $connection = null; | |
/** | |
* @var array|mixed | |
*/ | |
protected $data = []; | |
/** | |
* @var Connection | |
*/ | |
protected $currentClient = null; | |
/** | |
* @var Connection[] | |
*/ | |
protected $otherClients = []; | |
public function __construct(Request $request) | |
{ | |
$this->connection = $request->get('connection'); | |
$this->data = $request->get('data'); | |
$this->currentClient = $request->get('current_client'); | |
$this->otherClients = $request->get('other_clients'); | |
} | |
public function sendToOthers(array $data) { | |
foreach ($this->otherClients as $client) { | |
$client->send(json_encode($data)); | |
} | |
} | |
public function onOpen(Request $request) | |
{ | |
if (!Auth::check()) { | |
$this->currentClient->close(); | |
return; | |
} | |
echo 'Opened' . PHP_EOL; | |
echo $request->ip() . PHP_EOL; | |
$this->sendToOthers([ | |
'type' => 'USER_CONNECTED', | |
]); | |
} | |
public function onMessage(Request $request) | |
{ | |
if (!Auth::check()) { | |
$this->currentClient->close(); | |
return; | |
} | |
echo 'New message' . PHP_EOL; | |
echo $request->ip() . PHP_EOL; | |
$this->sendToOthers([ | |
'type' => 'MESSAGE_RECEIVED', | |
'data' => [ | |
'user' => Auth::user()->name, | |
'message' => $this->data->message, | |
] | |
]); | |
} | |
public function onClose(Request $request) | |
{ | |
echo 'Closed' . PHP_EOL; | |
echo $request->ip() . PHP_EOL; | |
$this->sendToOthers([ | |
'type' => 'USER_DISCONNECTED', | |
]); | |
} | |
public function onError(Request $request) | |
{ | |
echo 'Error' . PHP_EOL; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// in Laravel project root create also wsserver.php | |
// use 'php wsserver' to launch Web Socket server | |
// Make sure composer dependencies have been installed | |
require __DIR__ . '/vendor/autoload.php'; | |
use App\User; | |
use Illuminate\Support\Facades\Auth; | |
use Illuminate\Support\Facades\Session; | |
use Ratchet\MessageComponentInterface; | |
use Ratchet\ConnectionInterface; | |
/** | |
* chat.php | |
* Send any incoming messages to all connected clients (except sender) | |
*/ | |
class WebSocketLaravelServer implements MessageComponentInterface | |
{ | |
protected $clients; | |
public function __construct() { | |
echo 'Creating app...' . PHP_EOL; | |
$this->clients = new \SplObjectStorage; | |
} | |
protected function handleLaravelRequest(ConnectionInterface $con, $route, $data = null) | |
{ | |
/** | |
* @var \Ratchet\WebSocket\Version\RFC6455\Connection $con | |
* @var \Guzzle\Http\Message\Request $wsrequest | |
* @var \Illuminate\Http\Response $response | |
*/ | |
$params = [ | |
'connection' => $con, | |
'other_clients' => [], | |
]; | |
if ($data !== null) { | |
if (is_string($data)) { | |
$params = ['data' => json_decode($data)]; | |
} else { | |
$params = ['data' => $data]; | |
} | |
} | |
foreach ($this->clients as $client) { | |
if ($con != $client) { | |
$params['other_clients'][] = $client; | |
} else { | |
$params['current_client'] = $client; | |
} | |
} | |
$wsrequest = $con->WebSocket->request; | |
$app = require __DIR__.'/bootstrap/app.php'; | |
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); | |
$response = $kernel->handle( | |
$request = Illuminate\Http\Request::create($route, 'GET', $params, $wsrequest->getCookies()) | |
); | |
//var_dump(Auth::id()); | |
$controllerResult = $response->getContent(); | |
$kernel->terminate($request, $response); | |
return json_encode($controllerResult); | |
} | |
public function onOpen(ConnectionInterface $con) | |
{ | |
$this->clients->attach($con); | |
$this->handleLaravelRequest($con, '/websocket/open'); | |
} | |
public function onMessage(ConnectionInterface $con, $msg) | |
{ | |
$this->handleLaravelRequest($con, '/websocket/message', $msg); | |
} | |
public function onClose(ConnectionInterface $con) | |
{ | |
$this->handleLaravelRequest($con, '/websocket/close'); | |
$this->clients->detach($con); | |
} | |
public function onError(ConnectionInterface $con, \Exception $e) | |
{ | |
$this->handleLaravelRequest($con, '/websocket/error'); | |
echo 'Error: ' . $e->getMessage() . PHP_EOL; | |
$con->close(); | |
} | |
} | |
// Run the server application through the WebSocket protocol on port 8080 | |
$app = new Ratchet\App('localhost', 8080); | |
$app->route('/echo', new WebSocketLaravelServer); | |
$app->run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Maybe this code will help you
Also you have to use garbage collector like:
gc_collect_cycles();
after all because it still takes a lot of memory