PHP WebSocket
文章目录
- PHP WebSocket 介绍
- Laravel 8 中使用 WebSocket实现广播
- 1. 安装 Laravel WebSockets
- 2. 配置 WebSocket
- 3.运行 WebSocket 服务器
- 4. 客户端代码
- 5. 在 Laravel 中广播事件
- 6. 触发事件
- 7. 监听事件
- 创建单聊
- 1.创建一个用于发送单聊消息的事件
- 2.设置消息发送
- 3.设置路由
- 4.客户端 JavaScript 代码
- 总结
PHP WebSocket 介绍
WebSocket
是一种网络通信协议,允许在客户端和服务器之间建立持久的全双工连接。这种连接使得服务器能够主动向客户端推送数据,而不仅仅是响应请求。WebSocket
特别适合需要实时数据交互的应用,如聊天应用、在线游戏和实时通知
Laravel 8 中使用 WebSocket实现广播
在 Laravel
中,可以使用多个库来实现 WebSocket
,最常用的是 Ratchet
和 Beyond Code
的 Laravel WebSockets
1. 安装 Laravel WebSockets
使用 beyondcode/laravel-websockets 包
composer require beyondcode/laravel-websockets
2. 配置 WebSocket
安装完包后,需要发布配置文件
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider"
这个操作会创建 config/websockets.php
文件,您可以在其中配置 WebSocket
服务器的设置
3.运行 WebSocket 服务器
可以通过 Artisan
命令启动 WebSocket
服务器
php artisan websockets:serve
启动 WebSocket 服务器并在默认端口(6001)上监听
4. 客户端代码
使用 JavaScript 来连接到 WebSocket 服务器
// resources/js/app.js
const socket = new WebSocket('ws://localhost:6001');
socket.onopen = function() {
console.log('WebSocket connection established.');
};
socket.onmessage = function(event) {
console.log('Message from server: ', event.data);
};
socket.onclose = function() {
console.log('WebSocket connection closed.');
};
// 发送消息到服务器
socket.send('Hello, server!');
5. 在 Laravel 中广播事件
在事件中使用 ShouldBroadcast
接口
// app/Events/MessageSent.php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
public $message;
public function __construct($user, $message)
{
$this->user = $user;
$this->message = $message;
}
public function broadcastOn()
{
return new Channel('chat');
}
}
6. 触发事件
在控制器或其他需要的地方触发事件,以控制器为例
// app/Http/Controllers/ChatController.php
namespace App\Http\Controllers;
use App\Events\MessageSent;
use Illuminate\Http\Request;
class ChatController extends Controller
{
public function sendMessage(Request $request)
{
$user = $request->user(); // 获取当前用户
$message = $request->input('message');
// 触发广播事件
broadcast(new MessageSent($user, $message))->toOthers();
return response()->json(['status' => 'Message sent!']);
}
}
7. 监听事件
在客户端,可以使用 Laravel Echo
来监听事件
// 在 app.js 中
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
cluster: 'your-pusher-cluster',
forceTLS: true,
});
Echo.channel('chat')
.listen('MessageSent', (e) => {
console.log(e.user.name + ': ' + e.message);
});
确保在视图中引入这个 JavaScript
文件
<script src="{{ mix('js/app.js') }}"></script>
创建单聊
1.创建一个用于发送单聊消息的事件
// app/Events/PrivateMessageSent.php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class PrivateMessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $sender;
public $receiver;
public $message;
public function __construct($sender, $receiver, $message)
{
$this->sender = $sender;
$this->receiver = $receiver;
$this->message = $message;
}
public function broadcastOn()
{
// 使用私密频道,格式为 private-{userId}
return new PrivateChannel('private-chat.' . $this->receiver->id);
}
}
2.设置消息发送
创建一个控制器来处理消息的发送
// app/Http/Controllers/ChatController.php
namespace App\Http\Controllers;
use App\Events\PrivateMessageSent;
use Illuminate\Http\Request;
class ChatController extends Controller
{
public function sendMessage(Request $request)
{
// 验证请求数据
$request->validate([
'receiver_id' => 'required|exists:users,id',
'message' => 'required|string',
]);
$sender = $request->user(); // 获取当前用户
$receiver = User::find($request->receiver_id); // 获取接收者用户
// 触发广播事件
broadcast(new PrivateMessageSent($sender, $receiver, $request->message))->toOthers();
return response()->json(['status' => 'Message sent!']);
}
}
3.设置路由
在 routes/web.php
中添加路由
use App\Http\Controllers\ChatController;
Route::post('/send-private-message', [ChatController::class, 'sendMessage']);
4.客户端 JavaScript 代码
这里还是使用Laravel Echo
连接到 WebSocket
服务器并处理消息发送和接收
// resources/js/app.js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
cluster: 'your-pusher-cluster',
forceTLS: true,
});
// 连接到用户的私密频道
function connectToPrivateChannel(userId) {
window.Echo.private('private-chat.' + userId)
.listen('PrivateMessageSent', (e) => {
console.log(`${e.sender.name}: ${e.message}`);
// 这里可以更新 DOM 以显示消息
});
}
// 发送消息函数
function sendMessage(receiverId) {
const message = document.getElementById('message').value;
fetch('/send-private-message', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
},
body: JSON.stringify({ receiver_id: receiverId, message }),
})
.then(response => response.json())
.then(data => {
console.log(data.status);
})
.catch(error => console.error('Error:', error));
}
// 在 HTML 中调用 connectToPrivateChannel 和 sendMessage 方法
html代码
<!-- resources/views/chat.blade.php -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Private Chat</title>
<script src="{{ mix('js/app.js') }}"></script>
</head>
<body>
<div>
<h1>Private Chat Room</h1>
<div id="chat-box">
<!-- 这里将显示聊天记录 -->
</div>
<input type="text" id="message" placeholder="Type a message...">
<select id="receiver-id">
<!-- 动态加载用户列表 -->
@foreach($users as $user)
<option value="{{ $user->id }}">{{ $user->name }}</option>
@endforeach
</select>
<button onclick="sendMessage(document.getElementById('receiver-id').value)">Send</button>
</div>
</body>
</html>
总结
通过以上步骤我们可以在 Laravel 8
中实现聊天功能,实现用户之间进行通信,允许用户实时发送和接收消息,并通过 WebSocket
实时更新聊天记录,还可以根据需求扩展功能,例如添加消息存储、用户状态、聊天记录等