PHP Websocket開發(fā)教程,構(gòu)建實時問卷調(diào)查功能,需要具體代碼示例
Websocket技術(shù)是一種新興的網(wǎng)絡(luò)協(xié)議,它可以在 web 應(yīng)用中構(gòu)建實時通信功能。和傳統(tǒng)的 HTTP 協(xié)議不同,Websocket 協(xié)議可以實現(xiàn)雙向通信,并且能夠不間斷的發(fā)送和接收數(shù)據(jù)。在本文中,我們將會介紹如何使用 PHP 和 Websocket 技術(shù)構(gòu)建實時問卷調(diào)查功能,并提供具體的代碼示例。
- 在服務(wù)器上安裝 Ratchet
Ratchet 是一個 PHP 庫,用于開發(fā) Websocket 應(yīng)用程序。在開始之前,你需要在服務(wù)器上安裝 Ratchet 。使用以下命令:
composer require cboden/ratchet
登錄后復(fù)制
- 編寫 Websocket 服務(wù)器代碼
首先,我們需要創(chuàng)建一個 Ratchet 的 WebSocket 服務(wù)器。本示例中,我們將把所有代碼放在一個 PHP 文件中。在此文件中,我們將創(chuàng)建一個類,該類將擴(kuò)展 RatchetWebSocketWsServer 類。在構(gòu)造函數(shù)中,我們將初始化一個實例變量 $clients,該變量將存儲已連接的客戶端。
以下是服務(wù)器代碼:
<?php
require __DIR__ . '/vendor/autoload.php'; // 引入 ratchet
use RatchetMessageComponentInterface;
use RatchetConnectionInterface;
use RatchetWebSocketWsServer;
class PollServer implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo 'Client ' . $conn->resourceId . ' connected
';
}
public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
echo 'Client ' . $conn->resourceId . ' disconnected
';
}
public function onMessage(ConnectionInterface $from, $msg) {
echo 'Received message ' . $msg . ' from client ' . $from->resourceId . "
";
// 在這里處理邏輯...
}
public function onError(ConnectionInterface $conn, Exception $e) {
echo "An error has occurred: {$e->getMessage()}
";
$conn->close();
}
}
$server = new RatchetApp('localhost', 8080); // 創(chuàng)建一個新的 WebSocket 服務(wù)器
$server->route('/poll', new WsServer(new PollServer())); // 定義路由
$server->run(); // 啟動服務(wù)器
登錄后復(fù)制
上述代碼定義了一個名為 PollServer 的類,該類實現(xiàn)了 RatchetMessageComponentInterface 接口。 MessageComponentInterface 接口非常簡單,它只有四個方法,分別是 onOpen、onClose、onMessage 和 onError。這些方法會在客戶端連接到服務(wù)器時、從服務(wù)器斷開連接時、接收到新消息時和遇到錯誤時調(diào)用。在上面的代碼中,我們只是簡單地輸出了一些日志,但在處理實際邏輯時,你可以根據(jù)需要進(jìn)行更改。
接下來,我們需要將 PollServer 類傳遞給 RatchetWebSocketWsServer 類的構(gòu)造函數(shù)中。這將創(chuàng)建一個新的 WebSocket 服務(wù)器,該服務(wù)器將使用 WebSocket 協(xié)議與客戶端進(jìn)行通信。
最后,我們需要定義一個路由,以便客戶端可以連接到服務(wù)器。在上面的代碼中,我們定義了一個名為 /poll 的路由。在生產(chǎn)環(huán)境中,你應(yīng)該為 WebSocket 服務(wù)器使用真實的域名和端口。
- 編寫客戶端代碼
在本示例中,我們將使用 JavaScript 編寫客戶端代碼。首先,在 HTML 文件中添加以下代碼來創(chuàng)建一個 WebSocket 連接:
<!DOCTYPE html>
<html>
<head>
<title>Real-time Poll</title>
</head>
<body>
<h1>Real-time Poll</h1>
<script>
const connection = new WebSocket('ws://localhost:8080/poll'); // 替換為真實的域名和端口
connection.addEventListener('open', () => {
console.log('Connected');
});
connection.addEventListener('message', event => {
const message = JSON.parse(event.data);
console.log('Received', message);
});
connection.addEventListener('close', () => {
console.log('Disconnected');
});
connection.addEventListener('error', error => {
console.error(error);
});
</script>
</body>
</html>
登錄后復(fù)制
上面的代碼創(chuàng)建了一個名為 connection 的新 WebSocket 對象,并使用 ws://localhost:8080/poll 作為服務(wù)器 URL。在生產(chǎn)環(huán)境中,你應(yīng)該將此 URL 替換為真實的服務(wù)器域名和端口。
接下來,我們添加了幾個事件偵聽器,用于處理連接建立、接收消息、連接斷開和錯誤事件。在接收到消息時,我們使用 JSON.parse 將消息解析為 JavaScript 對象,并在控制臺上記錄。
- 實現(xiàn)實時問卷調(diào)查功能
現(xiàn)在我們已經(jīng)創(chuàng)建了 WebSocket 服務(wù)器和客戶端,我們需要實現(xiàn)實時問卷調(diào)查功能。考慮以下代碼示例:
public function onMessage(ConnectionInterface $from, $msg) {
echo 'Received message ' . $msg . ' from client ' . $from->resourceId . "
";
$data = json_decode($msg, true);
switch ($data['action']) {
case 'vote':
$vote = $data['vote'];
$this->broadcast([
'action' => 'update',
'votes' => [
'yes' => $this->getVoteCount('yes'),
'no' => $this->getVoteCount('no')
]
]);
break;
}
}
private function broadcast($message) {
foreach ($this->clients as $client) {
$client->send(json_encode($message));
}
}
private function getVoteCount($option) {
// 在這里查詢投票選項的數(shù)量...
}
登錄后復(fù)制
在上面的代碼中,我們在 onMessage 方法中處理客戶端發(fā)送的消息。此方法對消息進(jìn)行解碼,并使用 switch 語句檢查 action 字段。如果 action 等于 vote,則我們將更新投票計數(shù)并使用 broadcast 方法向所有客戶端發(fā)送更新結(jié)果。
在 broadcast 方法中,我們使用一個循環(huán)遍歷所有客戶端并將消息發(fā)送到每個客戶端。該方法將 JSON 編碼的消息發(fā)送到客戶端,客戶端將與 connection.addEventListener('message', ...) 事件處理程序中注冊的事件處理程序配合使用。
- 完整代碼示例
以下是本文中所有代碼示例的完整版本:
server.php:
<?php
require __DIR__ . '/vendor/autoload.php';
use RatchetMessageComponentInterface;
use RatchetConnectionInterface;
use RatchetWebSocketWsServer;
class PollServer implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo 'Client ' . $conn->resourceId . ' connected
';
}
public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
echo 'Client ' . $conn->resourceId . ' disconnected
';
}
public function onMessage(ConnectionInterface $from, $msg) {
echo 'Received message ' . $msg . ' from client ' . $from->resourceId . "
";
$data = json_decode($msg, true);
switch ($data['action']) {
case 'vote':
$vote = $data['vote'];
$this->broadcast([
'action' => 'update',
'votes' => [
'yes' => $this->getVoteCount('yes'),
'no' => $this->getVoteCount('no')
]
]);
break;
}
}
public function onError(ConnectionInterface $conn, Exception $e) {
echo "An error has occurred: {$e->getMessage()}
";
$conn->close();
}
private function broadcast($message) {
foreach ($this->clients as $client) {
$client->send(json_encode($message));
}
}
private function getVoteCount($option) {
// 在這里查詢投票選項的數(shù)量...
}
}
$server = new RatchetApp('localhost', 8080);
$server->route('/poll', new WsServer(new PollServer()));
$server->run();
登錄后復(fù)制
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Real-time Poll</title>
</head>
<body>
<h1>Real-time Poll</h1>
<form>
<label><input type="radio" name="vote" value="yes"> Yes</label>
<label><input type="radio" name="vote" value="no"> No</label>
<button type="submit">Vote</button>
</form>
<ul>
<li>Yes: <span id="yes-votes">0</span></li>
<li>No: <span id="no-votes">0</span></li>
</ul>
<script>
const connection = new WebSocket('ws://localhost:8080/poll');
connection.addEventListener('open', () => {
console.log('Connected');
});
connection.addEventListener('message', event => {
const message = JSON.parse(event.data);
if (message.action === 'update') {
document.getElementById('yes-votes').textContent = message.votes.yes;
document.getElementById('no-votes').textContent = message.votes.no;
}
});
connection.addEventListener('close', () => {
console.log('Disconnected');
});
connection.addEventListener('error', error => {
console.error(error);
});
document.querySelector('form').addEventListener('submit', event => {
event.preventDefault();
const vote = document.querySelector('input[name="vote"]:checked').value;
connection.send(JSON.stringify({
action: 'vote',
vote: vote
}));
});
</script>
</body>
</html>
登錄后復(fù)制
在以上代碼示例中,我們提供了一個簡單的 HTML 表單,用于向服務(wù)器發(fā)送投票結(jié)果。當(dāng)用戶提交表單時,我們將投票結(jié)果作為 JSON 對象發(fā)送到服務(wù)器上的 WebSocket 連接。
在客戶端收到更新消息時,我們在 HTML 中更新投票結(jié)果。
- 總結(jié)
在這篇文章中,我們介紹了如何使用 PHP 和 Websocket 技術(shù)構(gòu)建實時問卷調(diào)查功能,并提供了具體的代碼示例。Websocket 技術(shù)可以用于實現(xiàn)各種實時通信功能,如聊天室、游戲、實時更新等。如果你想要深入學(xué)習(xí) Websocket 技術(shù),我們建議你查看 Ratchet 的文檔,該文檔提供了很多關(guān)于 Websocket 開發(fā)的詳細(xì)指南和示例。






