# 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.

- Yayın: 2023-04-02
- Kategori: Web Geliştirme
- Etiketler: Laravel
- Okuma süresi: 3 dk okuma
- Kaynak: https://www.muhammetsafak.com.tr/blog/laravelde-gercek-zamanli-ozellikler-websocket-ve-broadcasting/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
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:

1. PHP'de bir `Event` sınıfı oluşturuyorsunuz ve `ShouldBroadcast` interface'ini implement ediyorsunuz.
2. O olayı fırlattığınızda Laravel, yapılandırılmış yayın sürücüsüne bir mesaj gönderiyor.
3. İstemci tarafında (JavaScript) `Echo` kütüphanesiyle aynı kanala abone oluyorsunuz.
4. Mesaj geldiğinde dinleyici çalışıyor.

```php
// 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](/blog/laravel-de-olaylar-events-ve-dinleyiciler) aynı:

```php
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:

```bash
npm install --save laravel-echo pusher-js
```

```javascript
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.

```php
// 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:

```php
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.
