移动端与Web端实时通知实现方案咨询(PHP+MySQL+Retrofit)
实现PHP+MySQL环境下的移动端与Web面板实时通知方案
1. 选择PHP WebSocket库:Ratchet
Ratchet是PHP生态中成熟的WebSocket实现,能无缝对接现有PHP后端,适合你的场景。
安装Ratchet
通过Composer安装依赖:
composer require cboden/ratchet
编写基础WebSocket服务器
创建websocket-server.php,实现连接管理和消息转发逻辑:
<?php require __DIR__ . '/vendor/autoload.php'; use Ratchet\MessageComponentInterface; use Ratchet\ConnectionInterface; use Ratchet\Server\IoServer; use Ratchet\Http\HttpServer; use Ratchet\WebSocket\WsServer; class ReportNotificationServer implements MessageComponentInterface { protected $adminConnections; public function __construct() { $this->adminConnections = new \SplObjectStorage; } // 验证管理员身份并保存连接 public function onOpen(ConnectionInterface $conn) { parse_str($conn->httpRequest->getUri()->getQuery(), $params); if (isset($params['admin_token']) && $this->validateAdminToken($params['admin_token'])) { $this->adminConnections->attach($conn); echo "管理员已连接: {$conn->resourceId}\n"; } else { $conn->close(); } } // 转发新报告通知给所有在线管理员 public function onMessage(ConnectionInterface $from, $msg) { $data = json_decode($msg, true); if ($data['type'] === 'new_report') { foreach ($this->adminConnections as $conn) { $conn->send(json_encode([ 'type' => 'new_report', 'report_id' => $data['report_id'], 'title' => $data['title'], 'timestamp' => date('Y-m-d H:i:s') ])); } } } public function onClose(ConnectionInterface $conn) { $this->adminConnections->detach($conn); echo "管理员已断开连接: {$conn->resourceId}\n"; } public function onError(ConnectionInterface $conn, \Exception $e) { echo "错误: {$e->getMessage()}\n"; $conn->close(); } // 自定义管理员token验证逻辑(从MySQL查询) private function validateAdminToken($token) { $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'db_user', 'db_pass'); $stmt = $pdo->prepare('SELECT id FROM admins WHERE token = ? AND is_active = 1'); $stmt->execute([$token]); return $stmt->rowCount() > 0; } } // 启动服务器,监听8080端口 $server = IoServer::factory( new HttpServer(new WsServer(new ReportNotificationServer())), 8080 ); echo "WebSocket服务器已启动,监听端口8080\n"; $server->run();
2. 在PHP API中触发通知
当用户通过Retrofit提交报告到API接口时,向WebSocket服务器发送通知:
// 提交报告的API接口示例 public function submitReport(Request $request) { // 1. 保存报告到MySQL $report = Report::create([ 'user_id' => $request->user_id, 'title' => $request->title, 'content' => $request->content ]); // 2. 向WebSocket服务器发送通知 $socket = fsockopen('localhost', 8080, $errno, $errstr, 30); if ($socket) { $msg = json_encode([ 'type' => 'new_report', 'report_id' => $report->id, 'title' => $report->title ]); // 构造WebSocket文本帧发送 $frame = "\x81" . chr(strlen($msg)) . $msg; fwrite($socket, $frame); fclose($socket); } return response()->json(['status' => 'success', 'report_id' => $report->id]); }
生产环境建议用Ratchet的Client组件或Redis做消息中转,提升可靠性
3. Web面板实现WebSocket客户端
在管理员面板前端添加WebSocket连接与消息监听:
const adminToken = '当前管理员的有效token'; // 从后端获取 const ws = new WebSocket(`ws://your-domain.com:8080?admin_token=${adminToken}`); ws.onopen = () => console.log('已连接到通知服务器'); ws.onmessage = (event) => { const data = JSON.parse(event.data); if (data.type === 'new_report') { // 显示通知并更新报告列表 alert(`新报告:${data.title}(ID: ${data.report_id})`); updateReportList(data.report_id); } }; ws.onclose = () => { console.log('连接断开,3秒后重连'); setTimeout(() => window.location.reload(), 3000); }; ws.onerror = (error) => console.error('WebSocket错误:', error);
4. 移动端实现WebSocket客户端
Retrofit是HTTP库,WebSocket需基于OkHttp实现(Retrofit依赖OkHttp):
添加OkHttp依赖
在build.gradle中添加:
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
编写WebSocket连接代码
import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.WebSocket import okhttp3.WebSocketListener import org.json.JSONObject class NotificationWebSocketListener : WebSocketListener() { override fun onOpen(webSocket: WebSocket, response: okhttp3.Response) { super.onOpen(webSocket, response) // 连接成功后的初始化操作 } override fun onMessage(webSocket: WebSocket, text: String) { super.onMessage(webSocket, text) val data = JSONObject(text) if (data.getString("type") == "report_approved") { // 处理管理员审批通知,调用系统通知 showSystemNotification("报告已审批", data.getString("report_title")) } } override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { super.onClosed(webSocket, code, reason) reconnect() } override fun onFailure(webSocket: WebSocket, t: Throwable, response: okhttp3.Response?) { super.onFailure(webSocket, t, response) reconnect() } private fun reconnect() { Thread.sleep(3000) startWebSocket() } private fun showSystemNotification(title: String, content: String) { // 实现Android/iOS系统通知逻辑 } } fun startWebSocket() { val client = OkHttpClient() val request = Request.Builder() .url("ws://your-domain.com:8080?user_token=当前用户的token") // 验证用户身份 .build() val listener = NotificationWebSocketListener() client.newWebSocket(request, listener) }
5. 可靠性优化建议
- 重连机制:客户端断开后自动重试连接,避免通知丢失
- 离线消息存储:管理员离线时,将通知保存到MySQL,上线后同步未读通知
- 身份验证:WebSocket连接必须验证身份,防止非法接入
- 负载均衡:用户量较大时,用Redis做消息中转,配合多WebSocket服务器实例
内容的提问来源于stack exchange,提问作者Samreen Aziz
相关产品推荐
相关产品推荐

