{"id":14974457,"url":"https://github.com/ollyxar/websockets-chat","last_synced_at":"2025-10-27T09:30:25.031Z","repository":{"id":57031046,"uuid":"107663853","full_name":"ollyxar/websockets-chat","owner":"ollyxar","description":"Laravel WebSockets chat","archived":false,"fork":false,"pushed_at":"2018-03-09T13:12:27.000Z","size":11,"stargazers_count":43,"open_issues_count":0,"forks_count":4,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-02-01T04:31:38.395Z","etag":null,"topics":["artisan-command","chat","laravel5","websocket-chat","websocket-server","websockets"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ollyxar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-20T10:15:15.000Z","updated_at":"2023-06-27T08:46:10.000Z","dependencies_parsed_at":"2022-08-23T18:50:46.790Z","dependency_job_id":null,"html_url":"https://github.com/ollyxar/websockets-chat","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ollyxar%2Fwebsockets-chat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ollyxar%2Fwebsockets-chat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ollyxar%2Fwebsockets-chat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ollyxar%2Fwebsockets-chat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ollyxar","download_url":"https://codeload.github.com/ollyxar/websockets-chat/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238471947,"owners_count":19478134,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["artisan-command","chat","laravel5","websocket-chat","websocket-server","websockets"],"created_at":"2024-09-24T13:50:35.604Z","updated_at":"2025-10-27T09:30:24.709Z","avatar_url":"https://github.com/ollyxar.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laravel WebSocket chat server\n\n![Version](https://poser.pugx.org/ollyxar/websockets-chat/v/stable.svg)\n![Downloads](https://poser.pugx.org/ollyxar/websockets-chat/d/total.svg)\n![License](https://poser.pugx.org/ollyxar/websockets-chat/license.svg)\n\n![logo](https://i.imgur.com/EAROGwT.jpg)\n\u003cmeta property=\"og:image\" content=\"https://i.imgur.com/EAROGwT.jpg\" /\u003e\n\n## Requirements\n\n* Unix (extension [pcntl_fork](http://php.net/manual/function.pcntl-fork.php))\n* PHP 7.1+\n* Laravel 5\n* composer\n\n## Installing WebSockets Chat\n\nThe recommended way to install WebSockets is through\n[Composer](http://getcomposer.org).\n\n\n```bash\n# Install Composer\ncurl -sS https://getcomposer.org/installer | php\n```\n\nNext, run the Composer command to install the latest stable version of WebSockets:\n\n```bash\nphp composer.phar require ollyxar/websockets-chat\n```\n\nAfter updating composer, add the service provider to the `providers` array in `config/app.php`\n\n```php\nOllyxar\\WSChat\\WSChatServiceProvider::class,\n```\n\n## Configuration\n\nYou can customize variables bellow by adding config-file: `websockets-chat.php` in the config folder:\n\n| parameter | description | example |\n| --- | --- | ---: |\n| handler  | Handler Class (extends of Worker) | `\\App\\MyHandler` |\n| host     | Host (ip)   |  `0.0.0.0` |\n| port     | Port        |  `2083`    |\n| worker_count | Count of forked process | `4` |\n| use_ssl  | Used protocol | `false` |\n| cert     | PEM certificate | `/etc/nginx/conf.d/wss.pem` |\n| pass_phrase | PEM certificate pass phrase | `secret$#%` |\n\n## Extended Handler class\n\nThis is example how to use Handler with User authentication. If you have default configuration and file-session-storage you can use this example.\n\nFirst you have to install auth-helper:\n \n ```bash\n php composer.phar require ollyxar/laravel-auth\n ```\n \n Then create your `Handler.php`:\n \n ```php\n namespace App;\n \nuse Generator;\nuse Ollyxar\\LaravelAuth\\FileAuth;\n// or you can use RedisAuth if you're storing sessions in the Redis-server:\n// use Ollyxar\\LaravelAuth\\RedisAuth;\nuse Ollyxar\\WebSockets\\{\n    Frame,\n    Handler as Worker,\n    Dispatcher\n};\n \n /**\n  * Class Handler\n  * @package App\n  */\n class Handler extends Worker\n {\n     /**\n      * Connected users\n      *\n      * @var array\n      */\n     protected $users = [];\n \n     /**\n      * Append connected user\n      *\n      * @param array $headers\n      * @param $socket\n      * @return bool\n      */\n     private function fillUser(array $headers, $socket): bool\n     {\n         if ($userId = FileAuth::getUserIdByHeaders($headers)) {\n             // allow only one connection for worker per user\n             if (!in_array($userId, $this-\u003eusers)) {\n                 $this-\u003eusers[(int)$socket] = $userId;\n                 return true;\n             }\n         }\n \n         return false;\n     }\n \n     /**\n      * @param $client\n      * @return Generator\n      */\n     protected function onConnect($client): Generator\n     {\n         $userName = User::where('id', (int)$this-\u003eusers[(int)$client])-\u003efirst()-\u003ename;\n         yield Dispatcher::async($this-\u003ebroadcast(Frame::encode(json_encode([\n             'type'    =\u003e 'system',\n             'message' =\u003e $userName . ' connected.'\n         ]))));\n     }\n \n     /**\n      * @param array $headers\n      * @param $socket\n      * @return bool\n      */\n     protected function validateClient(array $headers, $socket): bool\n     {\n         return $this-\u003efillUser($headers, $socket);\n     }\n \n     /**\n      * @param $clientNumber\n      * @return Generator\n      */\n     protected function onClose($clientNumber): Generator\n     {\n         $user = User::where('id', (int)@$this-\u003eusers[$clientNumber])-\u003efirst();\n         $userName = data_get($user, 'name', '[GUEST]');\n \n         yield Dispatcher::async($this-\u003ebroadcast(Frame::encode(json_encode([\n             'type'    =\u003e 'system',\n             'message' =\u003e $userName . \" disconnected.\"\n         ]))));\n \n         unset($this-\u003eusers[$clientNumber]);\n         yield;\n     }\n \n     /**\n      * @param string $message\n      * @param int $socketId\n      * @return Generator\n      */\n     protected function onClientMessage(string $message, int $socketId): Generator\n     {\n         $message = json_decode($message);\n         $userName = User::where('id', (int)$this-\u003eusers[$socketId])-\u003efirst()-\u003ename;\n         $userMessage = $message-\u003emessage;\n \n         $response = Frame::encode(json_encode([\n             'type'    =\u003e 'usermsg',\n             'name'    =\u003e $userName,\n             'message' =\u003e $userMessage\n         ]));\n \n         yield Dispatcher::async($this-\u003ebroadcast($response));\n     }\n }\n ```\n \nThen add markup to the front:\n \n```html\n\u003cdiv class=\"chat-wrapper\"\u003e\n    \u003cdiv class=\"message-box\" id=\"message-box\"\u003e\u003c/div\u003e\n    \u003cdiv class=\"panel\"\u003e\n        \u003cinput type=\"text\" name=\"message\" id=\"message\" placeholder=\"Message\"/\u003e\n        \u003cbutton id=\"send-btn\" class=\"button\"\u003eSend\u003c/button\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n```\n\nAnd JS code:\n\n```javascript\nvar wsUri = \"ws://laravel5.dev:2083\",\n    ws = new WebSocket(wsUri);\n\nws.onopen = function () {\n    var el = document.createElement('div');\n    el.classList.add('system-msg');\n    el.innerText = 'Connection established';\n    document.getElementById('message-box').appendChild(el);\n};\n\ndocument.getElementById('message').addEventListener('keydown', function (e) {\n    if (e.keyCode === 13) {\n        document.getElementById('send-btn').click();\n    }\n});\n\ndocument.getElementById('send-btn').addEventListener('click', function () {\n    var mymessage = document.getElementById('message').value;\n\n    if (mymessage === '') {\n        alert(\"Enter Some message Please!\");\n        return;\n    }\n\n    var objDiv = document.getElementById(\"message-box\");\n    objDiv.scrollTop = objDiv.scrollHeight;\n\n    var msg = {\n        message: mymessage\n    };\n    ws.send(JSON.stringify(msg));\n});\n\nws.onmessage = function (ev) {\n    var msg = JSON.parse(ev.data),\n        type = msg.type,\n        umsg = msg.message,\n        uname = msg.name;\n\n    var el = document.createElement('div');\n\n    if (type === 'usermsg') {\n        el.innerHTML = '\u003cspan class=\"user-name\"\u003e' + uname + '\u003c/span\u003e : \u003cspan class=\"user-message\"\u003e' + umsg + '\u003c/span\u003e';\n        document.getElementById('message-box').appendChild(el);\n    }\n    if (type === 'system') {\n        el.classList.add('system-msg');\n        el.innerText = umsg;\n        document.getElementById('message-box').appendChild(el);\n    }\n\n    document.getElementById('message').value = '';\n\n    var objDiv = document.getElementById('message-box');\n    objDiv.scrollTop = objDiv.scrollHeight;\n};\n\nws.onerror = function (e) {\n    var el = document.createElement('div');\n    el.classList.add('system-error');\n    el.innerText = 'Error Occurred - ' + e.data;\n    document.getElementById('message-box').appendChild(el);\n};\nws.onclose = function () {\n    var el = document.createElement('div');\n    el.classList.add('system-msg');\n    el.innerText = 'Connection Closed';\n    document.getElementById('message-box').appendChild(el);\n};\n```\n\n### Starting WebSocket Server\n\n```bash\nphp artisan websockets-chat:run\n```\n\n### Sending direct message to the server\n\n```bash\nphp artisan websockets-chat:send \"Hello from system!\"\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Follyxar%2Fwebsockets-chat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Follyxar%2Fwebsockets-chat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Follyxar%2Fwebsockets-chat/lists"}