# Laravel websockets

Сначала убедимся что в настройках `docker-compose.yml` открыт порт `6001` для нашего `laravel-websockets`

```yaml
ports:
    - "9000:9000"
    - "3000:3000" # дополнительный порт для websocket на котором будут крутиться (webpack,Vite)
    - "6001:6001" # дополнительный порт для laravel-websockets
```

установим пакет `beyondcode/laravel-websockets` и запустим публикацию конфига и миграций и саму миграцию:

```bash
composer require beyondcode/laravel-websockets
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
php artisan migrate
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
```

установим пакет `pusher/pusher-php-server`

```bash
composer require pusher/pusher-php-server
```

настроим .env

```systemd
BROADCAST_DRIVER=pusher
```

```systemd
PUSHER_APP_ID=livepost
PUSHER_APP_KEY=livepost_key
PUSHER_APP_SECRET=livepost_secret
```

```systemd
QUEUE_CONNECTION=sync
```

устанавливаем настройки в `options` в драйвере `pusher` в файле `broadcasting.php`

{% code title="config/broadcasting.php" %}

```php
'options' => [
    'host' => 'localhost',
    'port' => 6001,
    'scheme' => 'http',
    'encrypted' => false,
    'useTLS' => false,
],
```

{% endcode %}

запустим websockets и проверим подключение:

```
php artisan websockets:serve
```

и перейдём по адрессу `http://localhost:8098/laravel-websockets` при нажатии `Connect` мы должны увидить информацию про подключение:

<figure><img src="https://1562788351-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMyA51SCneIPcN69HMpat%2Fuploads%2FtMhhVBXTKUwd738Quuud%2F%D0%A1%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA%20%D1%8D%D0%BA%D1%80%D0%B0%D0%BD%D0%B0%202023-02-22%20%D0%B2%2017.35.18.png?alt=media&#x26;token=9574952a-69ff-4cf4-81d9-11140f6ea62c" alt=""><figcaption></figcaption></figure>

завершаем процесс нажатием `^+c`

расскоментируем `App\Providers\BroadcastServiceProvider::class` в нижней части `app.php`

создадим новый ивент:

```bash
php artisan make:event ChatMessageEvent
```

добавляем нашему ивенту интерфейс ShouldBroadcast

{% code title="app/Events/ChatMessageEvent.php" %}

```php
class ChatMessageEvent implements ShouldBroadcast
```

{% endcode %}

и настраиваем ивент:

{% code title="app/Events/ChatMessageEvent.php" %}

```php
private $message = null;

public function __construct(string $message){
    $this->message = $message;
}
// в какие каналы транслировать
public function broadcastOn(): array {
    return [
        new Channel('public.chat.1'),
    ];
}
// какое имя будет у ивента
public function broadcastAs(){
    return 'chat-message';
}
// какие данные передаст ивент
public function broadcastWith(){
    return ['message' => $this->message];
}
```

{% endcode %}

устанавливаем `laravel-echo` и `pusher-js@7.6.0` (надо устанавливать именно 7.6.0 так как в версиях выше уже не получится закомментировать cluster)

```bash
npm install laravel-echo 
npm i pusher-js@7.6.0
```

в resources/js/bootstrap.js раскомментируем код импорта и инициализации laravel-echo и pusher-js и настраиваем их конфиг как в [документации](https://beyondco.de/docs/laravel-websockets/basic-usage/pusher#usage-with-laravel-echo):

{% code title="resources/js/bootstrap.js" %}

```javascript
import Echo from 'laravel-echo';

import Pusher from 'pusher-js';
window.Pusher = Pusher;

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: import.meta.env.VITE_PUSHER_APP_KEY,
    // cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1',
    wsHost: window.location.hostname,
    wsPort: 6001,
    wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
    forceTLS: false,
    enabledTransports: ['ws', 'wss'],
    disableStats: true,
});
```

{% endcode %}

создаём представление `websocket.blade.php` подключаем в нём `app.js` и прописываем для него роут:

{% code title="resources/views/websocket.blade.php" %}

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="" id="form">
        <label for="input-message">Message:</label>
        <input type="text" id="input-message">
    </form>
    <ul id="list-messages"></ul>
    @vite(['resources/js/app.js'])
</body>
</html>
```

{% endcode %}

{% code title="routes/web.php" %}

```php
// вью с нашей формой и подключенным app.js
Route::get('/ws', function (){
    return view('websocket');
});

// роут который принимает post запрос который мы будем слать через axios
Route::post('/chat-message', function (\Illuminate\Http\Request $request){
    event(new \App\Events\ChatMessageEvent($request->message));
});
```

{% endcode %}

Объявляем наши каналы и дописываем отправку post запроса через axios в `resources/js/app.js`

{% code title="resources/js/app.js" %}

```javascript
import axios from "axios";

// отправляем содержимое формы через axios на роут /chat-message
const form = document.getElementById('form');
const inputMessage = document.getElementById('input-message');
form.addEventListener('submit', function(event){
    event.preventDefault();
    const userInput = inputMessage.value;
    axios.post('/chat-message',{
        message: userInput,
    });
});

const channel = Echo.channel('public.chat.1');
channel.subscribed(() => {
    // функиця вызовется когда мы подключемся к каналу
    console.log('subscribed!');
}).listen('.chat-message', (event) => {
    // функиця вызовется когда будет запущен ивент в канале на который мы подписаны
    console.log(event);
    const li = document.createElement('li');
    li.textContent = event.message;
    listMessages.append(li);
});
```

{% endcode %}

собираем все эти файлы через npm и опять запускаем websockets сервер:

```
npm run build
php artisan websockets:serve
```

переходим на `http://localhost:8098/ws` и видим в консоли `subscribed!` А при отправке формы, видим в консоли данные которые он отправил и сообщения из них добавляются в `ul list-message`. Оно будет доступно во всех вкладках которые подписаны на канал `public.chat.1`

{% hint style="info" %}
следующий урок на... <https://www.youtube.com/watch?v=9v18GD0-kdw>
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://overfinch.gitbook.io/cheatsheet/laravel/laravel-websockets.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
