Prečo Reverb, nie Pusher ani Ably
Real-time funkcie — live notifikácie, aktualizácia stavu objednávky bez reloadu, indikátor „admin práve píše" — sa v Laraveli tradične riešili cez Pusher alebo Ably. Obe sú SaaS platformy: platíte za správy, dáta prechádzajú ich servermi a pri výpadku závísite od tretej strany.
Laravel Reverb (vydaný v marci 2024, stabilný od Laravelu 11) je prvý WebSocket server, ktorý Laravel Team vydal priamo ako prvú stranu. Beží na vašom VPS, je open-source (MIT) a komunikuje rovnakým protokolom ako Pusher — takže Laravel Echo na frontende funguje bez zmeny.
| Riešenie | Hosťovanie | Cena | GDPR / dáta |
|---|---|---|---|
| Pusher | SaaS (cloudové servery) | od 49 USD/mes. | Dáta na cudzích serveroch |
| Ably | SaaS | od 25 USD/mes. | Dáta na cudzích serveroch |
| soketi (open-source) | Self-host | Zdarma | Vaše servery |
| Laravel Reverb | Self-host (váš VPS) | Zdarma (MIT) | Plná kontrola |
Inštalácia za 2 príkazy
Reverb vyžaduje Laravel 11+ a PHP 8.2+. Architektúru Laravelu 11 podrobne rozoberám v článku Prečo Laravel 12 v roku 2026 stále vyhráva.
# Inštalácia Reverbu
php artisan install:broadcasting
# Alebo manuálne:
composer require laravel/reverb
php artisan reverb:install
Príkaz install:broadcasting pridá balík, vytvorí konfiguračný súbor config/reverb.php a nastaví .env premenné. Do súboru .env doplňte:
BROADCAST_CONNECTION=reverb
REVERB_APP_ID=moja-aplikacia
REVERB_APP_KEY=super-tajny-kluc
REVERB_APP_SECRET=super-tajny-secret
REVERB_HOST=localhost
REVERB_PORT=8080
REVERB_SCHEME=http
# Pre frontend (Vite)
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"
REVERB_APP_KEY a REVERB_APP_SECRET môžu byť ľubovoľné reťazce — nie sú to API kľúče od Pusheru. Generujte ich cez php artisan key:generate --show alebo jednoducho openssl rand -hex 32.
Broadcasting event: nová objednávka
Každá real-time správa je v Laraveli event s rozhraniami ShouldBroadcast. Event definuje, na ktorý kanál správu pošlete a čo obsahuje.
php artisan make:event NewOrderPlaced
// app/Events/NewOrderPlaced.php
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class NewOrderPlaced implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(public Order $order) {}
public function broadcastOn(): array
{
// Private kanál — prístup iba po autentifikácii
return [
new PrivateChannel('orders.' . $this->order->user_id),
];
}
public function broadcastWith(): array
{
// Len tieto dáta prídu na frontend — nie celý Eloquent model
return [
'id' => $this->order->id,
'total' => number_format($this->order->total, 2),
'status' => $this->order->status,
];
}
// Voliteľné: vlastný názov eventu pre JS listener
public function broadcastAs(): string
{
return 'order.placed';
}
}
Event odosielate štandardným event() helperom — napríklad po uložení objednávky do databázy:
// app/Http/Controllers/OrderController.php
public function store(Request $request): RedirectResponse
{
$order = Order::create($request->validated());
// Broadcastovanie cez Reverb (asynchrónne, cez queue)
event(new NewOrderPlaced($order));
return redirect()->route('orders.show', $order);
}
php artisan queue:work. Ak chcete synchrónne odoslanie (vhodné len pri ladení), implementujte rozhranie ShouldBroadcastNow namiesto ShouldBroadcast.
Typy kanálov: public, private, presence
Reverb pozná tri typy kanálov, každý s iným účelom a úrovňou autentifikácie.
Public kanál — verejné udalosti
// V evente
return [new Channel('announcements')];
// JS
Echo.channel('announcements')
.listen('.new.announcement', (e) => console.log(e));
Private kanál — autentifikovaný prístup
Autorizačné pravidlo definujete v súbore routes/channels.php:
// routes/channels.php
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('orders.{userId}', function (User $user, int $userId) {
// Vráti true = prístup povolený, false = zakázaný
return (int) $user->id === (int) $userId;
});
Presence kanál — zoznam online používateľov
Presence kanál rozširuje private o zoznam všetkých pripojených používateľov — ideálne pre „kto je práve online" v adminu:
// routes/channels.php
Broadcast::channel('dashboard', function (User $user) {
if ($user->hasRole('admin')) {
// Dáta, ktoré uvidí každý iný člen kanálu
return ['id' => $user->id, 'name' => $user->name];
}
return false; // zamietnutý prístup
});
Laravel Echo na frontende
Frontend knižnica Laravel Echo spravuje WebSocket spojenie a mapuje kanály na JS callbacky. Funguje identicky s Pusherom — Reverb používa rovnaký protokol.
npm install laravel-echo pusher-js
// resources/js/bootstrap.js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'reverb',
key: import.meta.env.VITE_REVERB_APP_KEY,
wsHost: import.meta.env.VITE_REVERB_HOST,
wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
Praktický príklad: live notifikácie objednávok
// resources/js/orders.js
const userId = document.getElementById('app').dataset.userId;
// Private kanál — automaticky vyžiada auth cez /broadcasting/auth
Echo.private(`orders.${userId}`)
.listen('.order.placed', (e) => {
// Aktualizácia počítadla bez reloadu
const counter = document.getElementById('order-badge');
counter.textContent = parseInt(counter.textContent || '0') + 1;
counter.classList.remove('hidden');
// Toast notifikácia
showToast(`Nová objednávka #${e.id} — ${e.total} EUR`);
});
// Presence kanál — online admins
Echo.join('dashboard')
.here((users) => {
renderOnlineList(users);
})
.joining((user) => {
addToOnlineList(user);
})
.leaving((user) => {
removeFromOnlineList(user);
});
/broadcasting/auth pre autorizáciu private a presence kanálov. Ak používate API token autentifikáciu (Sanctum), pridajte do Echo konfigurácie authEndpoint: '/broadcasting/auth' a hlavičku Authorization: Bearer TOKEN.
Spustenie Reverbu
Počas vývoja stačí jeden príkaz:
php artisan reverb:start
# S debugovaním:
php artisan reverb:start --debug
Deploy na VPS: systemd + Nginx
Na produkčnom serveri musí Reverb bežať ako démon — systemd service zabezpečí automatické reštartovanie po výpadku.
systemd service
# /etc/systemd/system/laravel-reverb.service
[Unit]
Description=Laravel Reverb WebSocket Server
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/php artisan reverb:start --host=127.0.0.1 --port=8080
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
# Aktivácia a spustenie
sudo systemctl enable laravel-reverb
sudo systemctl start laravel-reverb
sudo systemctl status laravel-reverb
Nginx reverse proxy s SSL
WebSocket spojenie musí prechádzať cez Nginx — ten zabezpečí SSL terminovanie a presmeruje WSS traffic na Reverb bežiaci na porte 8080:
# /etc/nginx/sites-available/myapp
server {
listen 443 ssl;
server_name www.domena.sk;
# SSL certifikát (Let's Encrypt — návod v článku lets-encrypt-ssl)
ssl_certificate /etc/letsencrypt/live/domena.sk/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domena.sk/privkey.pem;
# Bežné HTTP requesty
location / {
proxy_pass http://127.0.0.1:9000; # PHP-FPM / Octane
proxy_set_header Host $host;
}
# WebSocket — Reverb
location /app {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 3600s;
}
}
proxy_read_timeout 3600s je kritické. Nginx predvolene vypína spojenie po 60 sekundách nečinnosti — WebSocket spojenie by sa rušilo každú minútu. Na produkčnom serveri nastavte hodnotu podľa očakávanej aktivity; 1 hodina (3600 s) je bezpečný základ.
Produkčné tipy: škálovanie a monitoring
- Redis adapter — pri viacerých PHP procesoch (Octane, PHP-FPM s viacerými workermi) musí Reverb synchronizovať stav cez Redis:
REVERB_DRIVER=redisv.env - Horizontálne škálovanie — viac Reverb inštancií za load balancerom vyžaduje Redis s Pub/Sub; pre väčšinu projektov stačí jedna inštancia
- Monitoring —
php artisan reverb:start --debugv logu ukazuje každé spojenie a event; pre produkciu nasmerujte log do súboru cezLOG_CHANNEL=daily - Počet spojení — jeden Reverb proces zvládne tisíce simultánnych WebSocket spojení; obmedzujúcim faktorom je zvyčajne RAM, nie CPU
- Queue worker — broadcastované eventy prechádzajú cez queue; monitorujte ich cez Laravel Horizon
Záver: checklist pred nasadením
- Reverb beží ako
systemdservice sRestart=always - Nginx má správne
Upgradehlavičky aproxy_read_timeout - Private kanály majú autorizačné pravidlá v
routes/channels.php - Broadcastované eventy idú cez queue (nie
ShouldBroadcastNow) - Queue worker beží a je monitorovaný
- Na produkčnom serveri s viacerými procesmi je nastavený Redis adapter
REVERB_SCHEME=httpsaVITE_REVERB_SCHEME=httpsv produkčnom.env
Reverb som nasadil na niekoľko projektov — rezervačný systém s live aktualizáciou dostupnosti termínov, e-commerce admin s notifikáciami nových objednávok a IoT dashboard aktualizujúci hodnoty senzorov každú sekundu. Vo všetkých prípadoch nahradil Pusher bez zmeny frontend kódu a s nulovými mesačnými nákladmi. Ak váš projekt potrebuje real-time funkcie a kombinujete ich s vlastným API, prečítajte si aj Ako navrhnúť REST API, ktoré nevyhorí o rok.