在今天的信息時代,在線投票系統成為了選舉、調查等活動中必不可少的一部分。與傳統的投票方式相比,在線投票系統不僅便于操作,而且速度快,可以實現實時統計數據等功能。
本文將介紹如何使用 PHP 的 Workerman 框架搭建一個基于 WebSocket 協議的在線投票系統。同時會給出具體的代碼示例,供讀者參考。
一、什么是 Workerman?
Workerman 是一款高性能、開源的 PHP 異步框架,它基于事件驅動思想,可以輕松地實現長連接應用,如 WebSocket、即時通訊等應用。
Workerman 支持 TCP、UDP 和 HTTP 等協議,具有高并發、低內存消耗等特點。相較于傳統的 Web 應用,Workerman 具有更強的實時性和穩定性,因此適用于在線游戲、聊天室、彈幕、消息推送等應用場景。
二、搭建 WebSocket 服務器
在開始之前,我們需要確保已經安裝了 PHP 環境,并且安裝了 Workerman 框架。具體的安裝流程可以參考官方文檔。
接下來,我們需要新建一個 PHP 文件,用于啟動 WebSocket 服務器,并且監聽客戶端發送的消息。假設我們在本地 127.0.0.1
的 8080
端口開啟 WebSocket 服務,代碼如下:
<?php require_once __DIR__ . '/vendor/autoload.php'; use WorkermanWorker; use WorkermanWebServer; use WorkermanProtocolsWebsocket; $ws_worker = new Worker('websocket://127.0.0.1:8080'); $ws_worker->count = 1; $ws_worker->onWorkerStart = function() { echo "WebSocket server started "; }; $ws_worker->onConnect = function($connection) { echo "New connection established: {$connection->id} "; }; $ws_worker->onMessage = function($connection, $data) { echo "Received a message from {$connection->id}: $data "; }; Worker::runAll();
登錄后復制
以上代碼中,我們使用 Workerman 的 Worker
類來開啟一個 WebSocket 服務器,并監聽 127.0.0.1
的 8080
端口。count
屬性指定了開啟的進程數。當有客戶端連接時,onConnect
回調函數將會被觸發;當有客戶端發送消息時,onMessage
回調函數將被觸發。我們可以在這兩個回調函數中處理客戶端的連接和消息。
三、實現在線投票系統
在投票系統中,我們需要支持多個用戶同時進行投票,并且需要實時地顯示投票結果。為了實現這樣的功能,我們需要使用 PHP 的共享內存機制,以及在客戶端和服務器之間傳遞數據的 JSON 格式。
首先,我們需要在服務器端定義一個關聯數組 $votes
,用于存儲每個投票選項的得票數。在每次接收到客戶端的投票請求時,我們會將對應的選項得票數加一,而不同選項的得票數則保存在不同的數組元素中。
<?php // ... $votes = [ 'Option 1' => 0, 'Option 2' => 0, 'Option 3' => 0, ]; $ws_worker->onMessage = function($connection, $data) use ($votes) { $data = json_decode($data, true); if (!isset($data['option']) || !isset($votes[$data['option']])) { // 投票選項不存在或者為空 $connection->send(json_encode([ 'code' => 400, 'message' => 'Invalid option' ])); return; } $votes[$data['option']]++; // 廣播投票結果 broadcast(json_encode([ 'code' => 200, 'message' => 'Vote successfully', 'data' => $votes ])); }; function broadcast($data) { global $ws_worker; foreach ($ws_worker->connections as $connection) { $connection->send($data); } }
登錄后復制
以上代碼中,我們使用了 PHP 的 global
關鍵字,將 $ws_worker
對象引入到 broadcast
函數中,在每次投票后將投票結果以 JSON 格式廣播給所有連接的客戶端。在上面的代碼中,我們還定義了一個 broadcast
函數,用于將消息發送給所有已連接的客戶端。
接下來,我們需要實現客戶端的投票功能。在 HTML 頁面中,我們可以通過 JavaScript 代碼創建 WebSocket 對象,用于與服務器進行實時通信。
<!DOCTYPE html> <html> <head> <title>WebSocket - Online Voting System</title> </head> <body> <h1>Online Voting System</h1> <p>Vote for your favorite option:</p> <form id="form"> <input type="radio" name="option" value="Option 1">Option 1<br> <input type="radio" name="option" value="Option 2">Option 2<br> <input type="radio" name="option" value="Option 3">Option 3<br> <input type="submit" value="Vote"> </form> <ul id="result"> <li>Option 1: <span id="vote1"></span></li> <li>Option 2: <span id="vote2"></span></li> <li>Option 3: <span id="vote3"></span></li> </ul> <script type="text/javascript"> var ws = new WebSocket('ws://127.0.0.1:8080'); ws.onopen = function() { console.log('WebSocket connected'); } ws.onmessage = function(event) { var data = JSON.parse(event.data); if (data.code === 200) { // 投票成功 updateVotes(data.data); } else { // 投票失敗 console.error(data.message); } } function updateVotes(votes) { document.querySelector('#vote1').innerHTML = votes['Option 1']; document.querySelector('#vote2').innerHTML = votes['Option 2']; document.querySelector('#vote3').innerHTML = votes['Option 3']; } var form = document.querySelector('#form'); form.addEventListener('submit', function(event) { event.preventDefault(); var option = document.querySelector('input[name="option"]:checked'); if (!option) { console.error('Please choose an option'); return; } var data = { option: option.value }; ws.send(JSON.stringify(data)); option.checked = false; }); </script> </body> </html>
登錄后復制
以上代碼中,我們使用了 WebSocket
對象的 onopen
、onmessage
兩個回調函數,分別用于在連接建立后輸出日志和接收來自服務器的消息。在表單中,我們使用 submit
事件來捕獲用戶投票的行為,并通過 WebSocket
對象將投票信息發送到服務器。在每次接收到服務器發送的投票結果時,我們會通過 updateVotes
函數更新 HTML 頁面中的投票數據。
四、總結
本文介紹了如何使用 PHP 的 Workerman 框架實現一個基于 WebSocket 協議的在線投票系統,并且給出了具體的代碼示例。通過本文的學習,讀者應該對 Workerman 框架、共享內存機制、WebSocket 協議等知識有了更深入的了解和掌握。