以下是使用 Vue + Laravel 8 封装 WebSocket 实现实时聊天的基本步骤:
- 安装 laravel-websockets 包。
composer require beyondcode/laravel-websockets
- 在 Laravel 项目中生成 JWT 认证密钥:
php artisan jwt:secret
- 安装 Laravel Echo 和 Pusher JS:
npm install laravel-echo pusher-js --save
- 在 Laravel 项目中创建 WebSocket 路由,用于监听 WebSocket 连接请求:
use BeyondCode\LaravelWebSockets\WebSocketsServiceProvider;
Route::get('/websocket', function () {
// 加载 WebSocket 服务
app(WebSocketsServiceProvider::class)->boot();
// 认证用户并与当前 WebSocket 连接绑定
auth()->loginUsingId(request()->get('user_id'));
// 开始监听连接请求
RatchetServerIoServer::factory(
new HttpServer(
new WsServer(
app(WebSocketsEventHandler::class)
)
),
env('WEBSOCKET_PORT')
)->run();
// 返回 OK 状态
return response('WebSocket server is running.');
});
- 创建
WebsocketsEventHandler
类,用于处理 WebSocket 消息:
use Illuminate\Support\Facades\Auth;
use BeyondCode\LaravelWebSockets\Events\WebsocketMessageReceived;
class WebsocketsEventHandler implements ShouldQueue
{
public function onMessage(WebsocketMessageReceived $event)
{
// 消息处理逻辑
}
}
- 创建
ChatMessage
Vue 组件,用于展示聊天信息以及发送新的聊天信息:
<template>
<div>
<div v-for="message in messages" :key="message.id">
{{ message.user.name }}: {{ message.text }}
</div>
<form @submit.prevent="send">
<input type="text" v-model="text">
<button type="submit">Send</button>
</form>
</div>
</template>
<script>
import Echo from "laravel-echo";
import Pusher from "pusher-js";
export default {
data() {
return {
messages: [],
text: "",
};
},
mounted() {
this.initEcho();
this.fetchMessages();
},
methods: {
initEcho() {
window.Echo = new Echo({
broadcaster: "pusher",
key: "YOUR_APP_KEY",
cluster: "YOUR_APP_CLUSTER",
forceTLS: true,
authEndpoint: "/api/authenticate",
auth: {
headers: {
Authorization:
"Bearer " + localStorage.getItem("access_token"),
},
},
});
window.Echo.join(`chat`).here((users) => {
console.log(users);
});
window.Echo.channel(`chat`).listen(".message.sent", (event) => {
this.messages.push(event.message);
});
},
fetchMessages() {
axios.get(`/api/chat/messages`).then((response) => {
this.messages = response.data.messages;
});
},
send() {
axios.post(`/api/chat/messages`, { text: this.text }).then(() => {
this.text = "";
});
},
},
};
</script>
- 创建
ChatMessageController
类,用于处理发送/接收聊天信息的 API 请求:
use Illuminate\Http\Request;
use App\Models\Message;
use Illuminate\Support\Facades\Auth;
use BeyondCode\LaravelWebSockets\Events\WebsocketMessageSent;
class ChatMessageController extends Controller
{
public function index()
{
$messages = Message::with('user')->get();
return response()->json([
'messages' => $messages
]);
}
public function store(Request $request)
{
$user = Auth::user();
$message = new Message([
'text' => $request->input('text')
]);
$message->user()->associate($user);
$message->save();
event(new WebsocketMessageSent('chat', [
'user_id' => $user->id,
'text' => $message->text,
]));
}
}
- 创建
JwtAuthMiddleware
类,用于验证用户身份并返回 JWT 认证令牌:
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Tymon\JWTAuth\Facades\JWTAuth;
class JwtAuthMiddleware
{
public function handle(Request $request, Closure $next)
{
try {
$user = JWTAuth::parseToken()->authenticate();
if ($user) {
$request->merge([
'user_id' => $user->id
]);
return $next($request);
}
} catch (\Throwable $e) {
return new Response('Unauthorized', 401);
}
}
}
- 在 Laravel 项目中添加路由,用于注册
JwtAuthMiddleware
中间件:
Route::middleware([JwtAuthMiddleware::class])->group(function () {
// ChatMessageController API 路由
});
这样,当你在 Vue 前端发送聊天信息时,该信息将会被转发给后端 Laravel 项目中的 WebsocketsEventHandler
类处理。然后使用 WebSocket 向所有连接的客户端广播该聊天信息。同时,在 Vue 前端监听订阅后,就能够接收 WebSocket 服务器发送的聊天信息,实现实时聊天的功能。