Laravel'de gerçek zamanlı özellikler: WebSocket ve broadcasting
Laravel Broadcasting ile anlık güncelleme eklemek: olay tabanlı yayın, Pusher entegrasyonu ve istemci tarafında dinlemek.
Bir uygulamada gerçek zamanlı (real-time) güncelleme ihtiyacı, HTTP’nin istek-yanıt döngüsünün dışına çıkmayı gerektirir. Kullanıcı sayfayı yenilediğinde yeni veriyi görmek yeterince iyi değil; sunucuda bir şey değiştiğinde istemcinin bunu anında bilmesi gerekiyor. Bildirimler, canlı sayaçlar, işlem durumu güncellemeleri — bunların hepsinde aynı ihtiyaç var.
Laravel, bu ihtiyacı Broadcasting katmanıyla karşılıyor. Olay tabanlı bir model: PHP tarafında bir olay fırlatıyorsunuz, o olay bir WebSocket kanalı üzerinden istemciye ulaşıyor. Altyapı olarak Pusher, Ably ya da kendi barındırdığınız Soketi kullanabilirsiniz.
Broadcasting nasıl çalışır
Temel akış şu şekilde işliyor:
- PHP’de bir
Eventsınıfı oluşturuyorsunuz veShouldBroadcastinterface’ini implement ediyorsunuz. - O olayı fırlattığınızda Laravel, yapılandırılmış yayın sürücüsüne bir mesaj gönderiyor.
- İstemci tarafında (JavaScript)
Echokütüphanesiyle aynı kanala abone oluyorsunuz. - Mesaj geldiğinde dinleyici çalışıyor.
// app/Events/OrderStatusUpdated.php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class OrderStatusUpdated implements ShouldBroadcast
{
public function __construct(
public readonly int $orderId,
public readonly string $status
) {}
public function broadcastOn(): Channel
{
return new Channel('orders.' . $this->orderId);
}
public function broadcastAs(): string
{
return 'status.updated';
}
}
Olayı fırlatmak normal Laravel olayıyla aynı:
broadcast(new OrderStatusUpdated($order->id, 'shipped'));
İstemci tarafında dinlemek
Laravel Echo, WebSocket kanallarını JavaScript’te yönetmek için resmi kütüphane. Pusher ile çalışmak için pusher-js paketine de ihtiyacınız var:
npm install --save laravel-echo pusher-js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
const echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
});
echo.channel('orders.' + orderId)
.listen('.status.updated', (data) => {
console.log('Sipariş durumu:', data.status);
// Arayüzü güncelle
});
Kanal türleri
Laravel üç tür kanal sunuyor:
Public Channel: Herhangi bir istemci abone olabilir. Genel bildirimler, canlı sayaçlar için uygundur.
Private Channel: Kanala abone olmadan önce kimlik doğrulama gerekir. Channel yerine PrivateChannel kullanılır; routes/channels.php dosyasında yetki kuralı tanımlanır.
// routes/channels.php
Broadcast::channel('orders.{orderId}', function ($user, $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});
Presence Channel: Özel kanalın üzerine “kanal üyelerini bilme” özelliğini ekler. Ortak çalışma alanları, “kim çevrimiçi” gibi özellikler için kullanılır.
broadcastWith ve veri şekillendirme
Olayın taşıyacağı veriyi özelleştirmek için broadcastWith metodunu kullanabilirsiniz. Varsayılan olarak Laravel, sınıfın tüm public özelliklerini gönderir; ama zaman zaman bu fazla veri içeriyor ya da ilişkili modeli eklemek istiyorsunuz:
public function broadcastWith(): array
{
return [
'order_id' => $this->orderId,
'status' => $this->status,
'label' => __('order.status.' . $this->status),
];
}
Bu metodu eklemeden unutursanız ve public alanda hassas bir alan varsa (örneğin kullanıcı ID’si, fiyat bilgisi), bu veri istemciye sızabilir. broadcastWith’i her olayda açıkça tanımlamak bu riski ortadan kaldırır.
Reverb: self-hosted seçenek
Pusher veya Ably gibi üçüncü parti servise bağımlı olmak istemiyorsanız, Laravel’in kendi WebSocket sunucusu olan Reverb’i barındırabilirsiniz. 2024 başında resmi olarak duyurulması bekleniyor; şu an Soketi alternatif olarak kullanılabiliyor.
Kendi altyapısını yönetmek isteyenler için beyondcode/laravel-websockets paketi hâlâ geçerli bir seçenek. Pusher protokolüyle uyumlu çalıştığı için istemci tarafı kodu değişmeden kalıyor.
Ne zaman WebSocket, ne zaman polling
WebSocket her senaryo için en iyi çözüm değil. Bağlantı sayısı arttıkça altyapı maliyeti de artıyor. Eğer “anlık” olması kritik değilse ve güncellemeler seyrekse, basit bir polling çoğu zaman daha az karmaşıklıkla aynı sonucu veriyor.
Kendi projemde şu ayrımı kullanıyorum: güncelleme kullanıcı bir eylem yaptıktan sonra yalnızca o kullanıcıyı ilgilendiriyorsa ve birkaç saniye gecikme kabul edilebilirse, polling yeterli. Birden fazla kullanıcının aynı veriyi anlık görmesi gerekiyorsa veya sunucu başlatıyor (push) ise WebSocket daha uygun.
WebSocket’in ayrıştığı alan şu: sunucudan istemciye mesaj akması gereken durumlar. Anlık bildirim, canlı ilerleme çubuğu, çok kullanıcılı etkileşim — bunlarda polling tatmin edici değil. Seçim her zaman ihtiyaçla orantılı olmalı.
Broadcasting katmanı, bu altyapıyı Laravel uygulama koduna entegre etmeyi gereksiz yere ağır olmaktan çıkarıyor. Olay fırlat, kanal tanımla, istemcide dinle. Bunların dışındaki ayrıntılar büyük ölçüde çerçeve tarafından yönetiliyor.