Laravel

Laravel 内置聊天室

配套视频地址:https://www.bilibili.com/video/av80196918


配置
  1. 打开 config/app.phpBroadcastServiceProvider 注释,即注册广播授权路由。
  2. .env 中配置驱动 BROADCAST_DRIVER=redis
  3. .env 中配置数据库
  4. 取消 config/database.php 中的 redis 前缀
'redis' => [
    'options' => [
        'prefix' => '',
    ],
];
安装服务

打开命令行,cd 到项目根目录下

npm install --save socket.io-client |  echo 'websocket 客户端'
npm install --save laravel-echo     |  echo 'websocket 客户端封装'
npm install -g laravel-echo-server  |  echo 'websocket 服务端'
npm install                         |  echo '安装所有其他依赖'
npm run watch                        |  echo '监控文件变化编译前端资源'
laravel-echo-server init             |  echo '初始化 websocket 服务端'
laravel-echo-server start            |  echo '启动 websocket 服务端'
初始化 websocket 客户端

resources/js/bootstrap.js 中添加以下代码

import Echo from "laravel-echo"

window.io = require('socket.io-client');

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':6001'
});
创建聊天室
Route::get('/login/user/{id}', fn($id) => auth()->loginUsingId($id));

Route::get('/room/{roomId}', function ($roomId) {
    broadcast(new \App\Events\Hello($roomId));
    return view('welcome', ['roomId' => $roomId]);
});
安装聊天室客户端
window.Echo.join(`chat.${roomId}`)
    .here((users) => {
        console.log(users);
    })
    .joining((user) => {
        console.log(user.name + ' 来了');
    })
    .leaving((user) => {
        console.log(user.name + ' 走了');
    });
安装频道认证路由
Broadcast::channel('chat.{roomId}', function ($user, $roomId) {
//    if ($user->canJoinRoom($roomId)) {
        return ['id' => $user->id, 'name' => $user->name];
//    }
});
定义聊天室事件
<?php

namespace App\Events;

use App\User;
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 Hello implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $user;
    public $roomId;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($roomId)
    {
        $this->user = auth()->user();
        $this->roomId = $roomId;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PresenceChannel('room.'.$this->roomId);
    }
}

开启聊天模式

监听聊天事件
window.Echo.join(`chat.${roomId}`)
    .here((users) => {
        console.log(users);
    })
    .joining((user) => {
        console.log(user.name + ' 来了');
    })
    .leaving((user) => {
        console.log(user.name + ' 走了');
    })
    .listen('NewMessage', (e) => {
        console.log(e.user.name + ":" + e.msg);
    });
定义聊天室群聊事件
<?php

namespace App\Events;

use App\User;
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\Log;

class NewMessage implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $user;
    public $roomId;
    public $msg;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($roomId, $msg)
    {
        $this->user = auth()->user();
        $this->roomId = $roomId;
        $this->msg = $msg;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PresenceChannel('chat.'.$this->roomId);
    }
}
安装聊天室群聊客户端
<!doctype html>
<html lang="en">
<head>
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <script>
        var roomId = "{{ $roomId }}";
    </script>
    <script src="/js/app.js"></script>
</head>
<body>
    <input type="text" id="msg">
    <button onclick="axios.get('/room/{{ $roomId }}/'+document.getElementById('msg').value)">发送</button>
</body>
</html>
定义聊天室群聊路由
Route::get('/room/{roomId}/{msg}', function ($roomId, $msg) {
    broadcast(new \App\Events\NewMessage($roomId, $msg))->toOthers();
});

发表评论