Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Питання на співбесіді: Broadcasting

Найпопулярніші питання з реальних Laravel/PHP співбесід для всіх рівнів

3 питання

Звичайний вебзастосунок відповідає лише на запит: сторінка оновиться тоді, коли її оновить користувач. Бродкастинг дозволяє серверу самому надіслати повідомлення у відкритий браузер - без перезавантаження й без опитування.

Навіщо: чат, сповіщення, лічильник онлайн, прогрес довгого завдання, оновлення списку без кнопки «оновити».

Як це виглядає. Подія позначається інтерфейсом:

class VacancyPublished implements ShouldBroadcast
{
    public function __construct(public Vacancy $vacancy)
    {
    }

    public function broadcastOn(): Channel
    {
        return new Channel('vacancies');
    }
}

Далі звичайне VacancyPublished::dispatch($vacancy) - і подія йде не лише слухачам на сервері, а й у браузер.

На клієнті її слухає Echo:

Echo.channel('vacancies')
    .listen('VacancyPublished', (e) => {
        console.log(e.vacancy.title);
    });

Що потрібно, крім коду: окремий сервіс, який тримає WebSocket-зʼєднання - Laravel Reverb (власний), Pusher чи Ably. PHP-процес сам зʼєднання не тримає.

Альтернатива, про яку варто памʼятати. Якщо оновлення рідкісні або потрібні лише одному користувачеві, звичайне опитування раз на кілька секунд чи wire:poll у Livewire простіші й не вимагають окремого сервера. Бродкастинг виправданий, коли подій багато, вони мають доходити миттєво й до багатьох одразу.

Докладніше в документації: Бродкастинг

Broadcasting транслює серверні події на клієнт через WebSockets - для оновлень у реальному часі (чати, нотифікації).

class MessageSent implements ShouldBroadcast
{
    public function broadcastOn(): array
    {
        return [new PrivateChannel('chat.'.$this->roomId)];
    }
}

На клієнті Laravel Echo підписується на канал:

Echo.private(`chat.${roomId}`)
    .listen('MessageSent', (e) => console.log(e.message));

Сервер WebSockets - Laravel Reverb (офіційний), Pusher або Soketi. Канали бувають public, private (з авторизацією) і presence (зі списком учасників).

Докладніше в документації: Broadcasting

Канали бувають трьох типів, і різниця між ними - саме в доступі.

Публічний - слухати може будь-хто, хто знає назву:

class VacancyPublished implements ShouldBroadcast
{
    public function broadcastOn(): Channel
    {
        return new Channel('vacancies');
    }
}

Годиться лише для того, що й так публічне.

Приватний - потребує авторизації:

public function broadcastOn(): PrivateChannel
{
    return new PrivateChannel('user.'.$this->user->id);
}

Правило описується в routes/channels.php:

Broadcast::channel('user.{userId}', function (User $user, int $userId) {
    return $user->id === $userId;
});

Клієнт спершу звертається до /broadcasting/auth, і лише отримавши підпис, підписується на канал.

Presence - приватний плюс список присутніх: хто зараз онлайн, хто друкує.

Де помиляються:

  • Публічний канал для приватних даних. Назву каналу видно у фронтенді, тож Channel('user.'.$id) слухається ким завгодно з перебором id.
  • Замикання авторизації, що завжди повертає true. Це те саме, що публічний канал, але виглядає безпечно.
  • Забувають, що подія несе всю модель. За замовчуванням у payload потрапляють усі публічні властивості - разом із полями, яких клієнт бачити не мусить. Формуйте payload явно через broadcastWith().
  • Приватні дані у назві каналу. Email чи токен у назві видно всім, хто дивиться трафік.

Практично: усе, що стосується конкретного користувача, - PrivateChannel; payload завжди явний.

Докладніше в документації: Бродкастинг