https://github.com/ollyxar/websockets-chat
Laravel WebSockets chat
https://github.com/ollyxar/websockets-chat
artisan-command chat laravel5 websocket-chat websocket-server websockets
Last synced: 8 months ago
JSON representation
Laravel WebSockets chat
- Host: GitHub
- URL: https://github.com/ollyxar/websockets-chat
- Owner: ollyxar
- License: mit
- Created: 2017-10-20T10:15:15.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2018-03-09T13:12:27.000Z (over 8 years ago)
- Last Synced: 2025-02-01T04:31:38.395Z (over 1 year ago)
- Topics: artisan-command, chat, laravel5, websocket-chat, websocket-server, websockets
- Language: PHP
- Homepage:
- Size: 10.7 KB
- Stars: 43
- Watchers: 7
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Laravel WebSocket chat server




## Requirements
* Unix (extension [pcntl_fork](http://php.net/manual/function.pcntl-fork.php))
* PHP 7.1+
* Laravel 5
* composer
## Installing WebSockets Chat
The recommended way to install WebSockets is through
[Composer](http://getcomposer.org).
```bash
# Install Composer
curl -sS https://getcomposer.org/installer | php
```
Next, run the Composer command to install the latest stable version of WebSockets:
```bash
php composer.phar require ollyxar/websockets-chat
```
After updating composer, add the service provider to the `providers` array in `config/app.php`
```php
Ollyxar\WSChat\WSChatServiceProvider::class,
```
## Configuration
You can customize variables bellow by adding config-file: `websockets-chat.php` in the config folder:
| parameter | description | example |
| --- | --- | ---: |
| handler | Handler Class (extends of Worker) | `\App\MyHandler` |
| host | Host (ip) | `0.0.0.0` |
| port | Port | `2083` |
| worker_count | Count of forked process | `4` |
| use_ssl | Used protocol | `false` |
| cert | PEM certificate | `/etc/nginx/conf.d/wss.pem` |
| pass_phrase | PEM certificate pass phrase | `secret$#%` |
## Extended Handler class
This is example how to use Handler with User authentication. If you have default configuration and file-session-storage you can use this example.
First you have to install auth-helper:
```bash
php composer.phar require ollyxar/laravel-auth
```
Then create your `Handler.php`:
```php
namespace App;
use Generator;
use Ollyxar\LaravelAuth\FileAuth;
// or you can use RedisAuth if you're storing sessions in the Redis-server:
// use Ollyxar\LaravelAuth\RedisAuth;
use Ollyxar\WebSockets\{
Frame,
Handler as Worker,
Dispatcher
};
/**
* Class Handler
* @package App
*/
class Handler extends Worker
{
/**
* Connected users
*
* @var array
*/
protected $users = [];
/**
* Append connected user
*
* @param array $headers
* @param $socket
* @return bool
*/
private function fillUser(array $headers, $socket): bool
{
if ($userId = FileAuth::getUserIdByHeaders($headers)) {
// allow only one connection for worker per user
if (!in_array($userId, $this->users)) {
$this->users[(int)$socket] = $userId;
return true;
}
}
return false;
}
/**
* @param $client
* @return Generator
*/
protected function onConnect($client): Generator
{
$userName = User::where('id', (int)$this->users[(int)$client])->first()->name;
yield Dispatcher::async($this->broadcast(Frame::encode(json_encode([
'type' => 'system',
'message' => $userName . ' connected.'
]))));
}
/**
* @param array $headers
* @param $socket
* @return bool
*/
protected function validateClient(array $headers, $socket): bool
{
return $this->fillUser($headers, $socket);
}
/**
* @param $clientNumber
* @return Generator
*/
protected function onClose($clientNumber): Generator
{
$user = User::where('id', (int)@$this->users[$clientNumber])->first();
$userName = data_get($user, 'name', '[GUEST]');
yield Dispatcher::async($this->broadcast(Frame::encode(json_encode([
'type' => 'system',
'message' => $userName . " disconnected."
]))));
unset($this->users[$clientNumber]);
yield;
}
/**
* @param string $message
* @param int $socketId
* @return Generator
*/
protected function onClientMessage(string $message, int $socketId): Generator
{
$message = json_decode($message);
$userName = User::where('id', (int)$this->users[$socketId])->first()->name;
$userMessage = $message->message;
$response = Frame::encode(json_encode([
'type' => 'usermsg',
'name' => $userName,
'message' => $userMessage
]));
yield Dispatcher::async($this->broadcast($response));
}
}
```
Then add markup to the front:
```html
Send
```
And JS code:
```javascript
var wsUri = "ws://laravel5.dev:2083",
ws = new WebSocket(wsUri);
ws.onopen = function () {
var el = document.createElement('div');
el.classList.add('system-msg');
el.innerText = 'Connection established';
document.getElementById('message-box').appendChild(el);
};
document.getElementById('message').addEventListener('keydown', function (e) {
if (e.keyCode === 13) {
document.getElementById('send-btn').click();
}
});
document.getElementById('send-btn').addEventListener('click', function () {
var mymessage = document.getElementById('message').value;
if (mymessage === '') {
alert("Enter Some message Please!");
return;
}
var objDiv = document.getElementById("message-box");
objDiv.scrollTop = objDiv.scrollHeight;
var msg = {
message: mymessage
};
ws.send(JSON.stringify(msg));
});
ws.onmessage = function (ev) {
var msg = JSON.parse(ev.data),
type = msg.type,
umsg = msg.message,
uname = msg.name;
var el = document.createElement('div');
if (type === 'usermsg') {
el.innerHTML = '' + uname + ' : ';
document.getElementById('message-box').appendChild(el);
}
if (type === 'system') {
el.classList.add('system-msg');
el.innerText = umsg;
document.getElementById('message-box').appendChild(el);
}
document.getElementById('message').value = '';
var objDiv = document.getElementById('message-box');
objDiv.scrollTop = objDiv.scrollHeight;
};
ws.onerror = function (e) {
var el = document.createElement('div');
el.classList.add('system-error');
el.innerText = 'Error Occurred - ' + e.data;
document.getElementById('message-box').appendChild(el);
};
ws.onclose = function () {
var el = document.createElement('div');
el.classList.add('system-msg');
el.innerText = 'Connection Closed';
document.getElementById('message-box').appendChild(el);
};
```
### Starting WebSocket Server
```bash
php artisan websockets-chat:run
```
### Sending direct message to the server
```bash
php artisan websockets-chat:send "Hello from system!"
```