Laravel broadcasting với pusher
Cài đặt gói pusher vào trong app laravel :
composer require pusher/pusher-php-server
Sau đó chúng ta sẽ tạo route xác thực :
Route::post('/pusher/auth', [\App\Http\Controllers\UserController::class, 'useauth_private'])->name('userauth');
Route::post('/pusher/presenceauth', [\App\Http\Controllers\UserController::class, 'useauth_presence'])->name('presenceauth');
Phương thức useauth_private trong UserController :
public function useauth_private(Request $request)
    {
        $pusher = new Pusher(env('PUSHER_APP_KEY'),env('PUSHER_APP_SECRET'),env('PUSHER_APP_ID'),[
            'cluster'=>env('PUSHER_APP_CLUSTER')
        ]);
        $user_id = Auth::id();
        Log::info($user_id);
        $channel_name = $request->channel_name;
        if ($channel_name !== 'private-chat-' . $user_id && $channel_name !== 'private-order-' . $user_id) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }
        // Trả về thông tin user cho presence channel
        return response($pusher->authorizeChannel($request->channel_name, $request->socket_id));
    }
Phương thức userauth_presence
public function useauth_presence(Request $request){
        if (!Auth::check()) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }
        $pusher = new Pusher(
            env('PUSHER_APP_KEY'),
            env('PUSHER_APP_SECRET'),
            env('PUSHER_APP_ID'),
            ['cluster' => env('PUSHER_APP_CLUSTER')]
        );
        $user = Auth::user();
        $presence_data = [
            'id' => $user->id,
            'name' => $user->name,
            'email' => $user->email
        ];
        return response($pusher->authorizePresenceChannel($request->channel_name, $request->socket_id, $presence_data));
    }
Trong file .env :
PUSHER_APP_ID="2222"
PUSHER_APP_KEY="2222"
PUSHER_APP_SECRET="2222"
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME="https"
PUSHER_APP_CLUSTER="ap1"
Trong file : bootstrap/app.php thêm đoạn code :
$middleware->validateCsrfTokens(['/pusher/auth','/pusher/presenceauth']);
để loại bỏ csrf với các url
Còn ở frontend blade :
  <!-- Pusher -->
    <script src="https://js.pusher.com/8.2.0/pusher.min.js"></script>
    <script>
        // comment để bỏ log dòng sau : 
        Pusher.logToConsole = true;
        var pusher = new Pusher('{{ env('PUSHER_APP_KEY') }}', {
            cluster: 'ap1',
            userAuthentication:{
                endpoint: "{{ route('userauth') }}",
                params: {
                    _token: document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || ''
                },
                headers: {
                    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                },
                customHandler: null,
            },
            presenceAuthentication: {
                endpoint: "{{ route('presenceauth') }}",
                transport: 'ajax',
                params: {
                    _token: document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || ''
                },
                headers: {
                    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                },
            }
        });
        var userId = "{{ \Illuminate\Support\Facades\Auth::id() ?? '' }}"; // Nếu user chưa đăng nhập thì là ''
        if (userId) {
            var private_channel = ['private-chat-', 'private-order-'];
            private_channel.forEach((channel) => {
                const subscribedChannel = pusher.subscribe(channel + userId);
                subscribedChannel.bind("chat", function (data) {
                    console.log("New private event:", data);
                    alert(JSON.stringify(data));
                });
            });
            var presence_channel = ['presence-chat', 'presence-order'];
            presence_channel.forEach((channel) => {
                const subscribedChannel = pusher.subscribe(channel);
                // Lắng nghe sự kiện khi có người dùng mới tham gia kênh
                subscribedChannel.bind("pusher:subscription_succeeded", function (members) {
                    console.log("🔹 User list:", members);
                    document.getElementById("messages").innerHTML += "<p>✅ Connected to presence channel: " + channel + "</p>";
                });
                // Lắng nghe khi có người tham gia
                subscribedChannel.bind("pusher:member_added", function (member) {
                    console.log("➕ New member joined:", member);
                });
                // Lắng nghe khi có người rời khỏi
                subscribedChannel.bind("pusher:member_removed", function (member) {
                    console.log("❌ Member left:", member);
                });
                // Lắng nghe tin nhắn trong kênh
                subscribedChannel.bind("chat", function (data) {
                    console.log("📩 Presence Chat:", data);
                    alert(JSON.stringify(data));
                });
            });
        }
        var public_channel = ['public-chat', 'public-order'];
        public_channel.forEach((channel) => {
            const subscribedChannel = pusher.subscribe(channel);
            subscribedChannel.bind("chat", function (data) {
                console.log("New public event:", data);
                document.getElementById("messages").innerHTML += "<p>" + data.message + "</p>";
                alert(JSON.stringify(data));
            });
        });
    </script>
Trong controller ta code như sau để dùng broadcast public và private :
<?php
namespace App\Http\Controllers;
use App\Events\PrivateEvent;
use App\Events\Pusher\PublicEvent;
use App\Events\ThongbaoEvent;
use Illuminate\Http\Request;
class NotificationController extends Controller
{
    public function public()
    {
        $message = 'Xin chào';
        broadcast(new PublicEvent($message));
        return response()->json(['message' => 'Notification pusher public sent']);
    }
    public function private(){
        $message = 'Xin chào private test channel';
        broadcast(new \App\Events\Pusher\PrivateEvent($message,2));
        return response()->json(['message' => 'Notification private sent']);
    }
}
Event Public :
<?php
namespace App\Events\Pusher;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class PublicEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    /**
     * Create a new event instance.
     */
    public $message;
    public function __construct($message)
    {
        $this->message = $message;
    }
    /**
     * Get the channels the event should broadcast on.
     *
     * @return array<int, \Illuminate\Broadcasting\Channel>
     */
    public function broadcastOn()
    {
        return [
            new Channel('public-chat'),
        ];
    }
    public function broadcastAs(){
        return 'chat';
    }
}
Event Private :
<?php
namespace App\Events\Pusher;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class PrivateEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    /**
     * Create a new event instance.
     */
    public $message;
    public  $user_id ;
    public function __construct($message,$user_id)
    {
        $this->user_id = $user_id;
        $this->message = $message;
    }
    /**
     * Get the channels the event should broadcast on.
     *
     * @return array<int, \Illuminate\Broadcasting\Channel>
     */
    public function broadcastOn()
    {
        $tenchanel = 'private-chat-'.$this->user_id;
        Log::info($tenchanel);
        return [
            new PrivateChannel($tenchanel),
        ];
    }
    public function broadcastAs(){
        return 'chat';
    }
    public function broadcastWith(){
        return [
            'message' => $this->message,
        ];
    }
}
Như vậy là đã xong .Ở đây mình đã test private còn presence thì chưa nhé
 
                                    
                 
                 
                 
                