Руководство по использованию сокетов в Laravel

Руководство по сокетам в Laravel

Сегодня сокеты очень популярны в веб-разработке. Они обеспечивают связь в реальном времени между браузером клиента и сервером. Есть много вариантов использования. Например, сокеты могут быть использованы для уведомлений или чатов. В этой статье я покажу вам, как использовать сокеты в приложении Laravel для чатов. Я буду использовать Pusher для трансляции своих событий, но вы можете использовать для этого Redis или Socket.io. В первой части этой статьи мы сделаем серверную часть приложения, а во второй части мы сосредоточимся на внешнем интерфейсе.

Часть 1: Бэкэнд

Pusher

Поскольку мы собрались транслировать наши события через Pusher, то мы должны установить его через Composer.

composer require pusher/pusher-php-server "~3.0"

Примечание: Для использования Pusher вам понадобится аккаунт. Вы можете создать бесплатную учетную запись на https://pusher.com

После того, как создали Pusher аккаунт, надо создать приложение в Pusher. После этого надо добавить в ваш файл .env идентификатор приложения, ключ, секрет и кластер. Используйте для этого PUSHER_APP_ID, PUSHER_APP_KEY, PUSHER_APP_SECRET и PUSHER_APP_CLUSTER. И измените BROADCAST_DRIVER на pusher.

socket laravel
Необходимые данные будут показаны на панели инструментов после выбора приложения

Время начать делать чат

Теперь, когда мы установили зависимости и настроили приложение Pusher, пришло время начать cделать чат. Давайте кратко рассмотрим, что мы будем делать. Создадим компонент Vue для чата, который будет отправлять запрос на контроллер API с сообщением, отправленным пользователем. Это будет реализовано во второй части этой статьи. Для бэкэнда мы создадим контроллер API, который будет транслировать событие, информируя других клиентов о сообщении, которое было отправлено в чат.

Создание контроллера

Начнем с создания контроллера, который будет обрабатывать входящие запросы:

php artisan make:controller ChatController

Он очень простой. Если запрос содержит сообщение, мы инициируем событие, иначе ничего не делаем. Это событие будет транслировать сообщение всем клиентам.

namespace App\Http\Controllers;
use App\Events\MessageSend;
use Illuminate\Http\Request;
class ChatController extends Controller
{
    public function index(Request $request)
    {
        $message = $request->input('message', '');
        if (strlen($message)) {
            event(new MessageSend($message));
        }
    }
}

Нам также нужно создать маршрут в файле routes/api.php.

Route::post('/message', 'ChatController@index');

 

Событие

Как мы видели в ChatController, инициируется событие MessageSend. Это событие должно транслироваться другим клиентам, чтобы они знали, что сообщение было отправлено в окно чата. Давайте создадим это событие:

php artisan make:event MessageSend

Класс MessageSend будет транслироваться в канал chatbox, являющийся публичным. Это определяется в методе broadcastOn.

Вот как выглядит реализация:

namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class MessageSend implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    public $message;
    public function __construct($message)
    {
        $this->message = $message;
    }
    public function broadcastOn()
    {
        return new Channel('chatbox');
    }
}

Примечание: Класс MessageSend реализует интерфейс ShouldBroadcast.

 

BroadcastServiceProvider

Прежде чем мы сможем начать трансляцию, надо зарегистрировать App\Providers\BroadcastServiceProvider. Это можно сделать, раскомментировав этого провайдера в массиве провайдеров в файле config/app.php.

Laravel sockets

Поскольку мы внесли изменения в конфиг, то нам нужно выполнить следующую команду, чтобы обновить файл кэша конфигурации:

php artisan config:cache

 

Часть 2: Интерфейс

Получение трансляций

Для получения трансляций мы будем использовать библиотеку Javascript, которая называется Laravel Echo. Эта библиотека позволяет очень легко слушать трансляции и подписываться на каналы. Мы также установим pusher-js, так как мы используем Pusher для трансляции.

npm install --save laravel-echo pusher-js

После того, как мы установили Laravel Echo и Pusher, мы должны создать экземпляр Laravel Echo в приложении. В конце файла resources/js/bootstrap.js находится код, который создает экземпляр Laravel Echo. Раскомментируйте эту часть кода.

Ларавел сокеты

Чат

Как говорилось выше, создадим компонент Vue, который отправляет запрос нашему API при отправке сообщения. Сделаем это прямо сейчас.

Создаем ChatboxComponent.vue в папке resources/js/components. Этот компонент содержит очень простую форму, которая отправляет запрос в конечную точку /api/message. Кроме этого, компонент прослушивает событие MessageSend на канале чата. Каждый раз, когда он получает сообщение, то добавляет его в окно чата.

<template>
    <div class="chatbox p-3">
        <div class="messages" v-if="messages.length">
            <div class="message" v-for="message in messages">
                <span class="d-inline-block">{{ message }}</span>
            </div>
        </div>

        <div class="row mt-5">
            <div class="col-3">
                <input type="text" class="form-control" v-model="textMessage"></input>
            </div>
        </div>

        <div class="row mt-2">
            <div class="col">
                <button class="btn btn-primary" @click="sendMessage()">Send</button>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                textMessage: '',
                messages: [],
            }
        },
        created() {
            this.addMessage('You joined the chatbox.');
            Echo.channel('chatbox')
                .listen('MessageSend', (e) => {
                    this.addMessage(e.message);
                });
        },
        methods: {
            addMessage(message) {
                let date= new Date();
                let timestamp = date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
                this.messages.push(timestamp + ' ' + message);
            },
            sendMessage() {
                axios.post('/api/message', {message: this.textMessage});
                this.textMessage = '';
            }
        }
    }
</script>

Теперь, когда мы создали ChatboxComponent, давайте изменим welcome.blade.php, чтобы он использовал этот компонент.

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="csrf-token" content="{{ csrf_token() }}">
        <title>Chatbox</title>

        <script src="{{ asset('js/app.js') }}" defer></script>
        <script src="{{ asset('js/bootstrap.min.js') }}"></script>
        <link href="{{ asset('css/app.css') }}" rel="stylesheet">
    </head>
    <body>
        <div id="app">
            <chatbox-component></chatbox-component>
        </div>
    </body>
</html>

Чтобы убедиться, что компонент зарегистрирован, надо раскомментировать следующие строки в файле resources/js/app.js.

Сокеты в Laravel

Эти две строки кода автоматически зарегистрируют ваши компоненты Vue. Не забудьте запустить

npm run watch

 

Поболтаем

Теперь можно начать общение в чате. Чтобы протестировать приложение, откройте две вкладки в вашем браузере, одну из них в режиме инкогнито и просто начните печатать!
Пример чата на сокетах Laravel

Отладка

Если у вас возникнут какие-либо проблемы, то в Pusher есть отличная консоль отладки, которая будет логировать любые действия, происходящие в ваших сокетах. Просто перейдите на панель инструментов Pusher и выберите вкладку Debug console. Вы можете проверить, подключается ли клиент к Pusher и транслируются ли события.

BroadcastException

В зависимости от среды, в которой вы разрабатываете, вы можете получить BroadcastException при попытке передать событие. Это можно исправить, добавив следующий код в массив pusher.options в файле config/broadcasting.php.

'curl_options' => [
    CURLOPT_SSL_VERIFYHOST => 0,
    CURLOPT_SSL_VERIFYPEER => 0,
],

Поздравляю! Чат готов. Я надеюсь, что эта статья помогла вам реализовать сокеты в Laravel.

Удачного кодирования!

 

Автор: Daan
Перевод: Алексей Широков

Наш Телеграм-канал — следите за новостями о Laravel.