WebSocket en PHP : création d'applications temps réel de niveau avancé

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

WebSocket en PHP : de la théorie à l'application temps réel industrielle



Le protocole WebSocket a révolutionné le développement web en permettant de créer des canaux de communication bidirectionnels complets entre le client et le serveur. Contrairement à l'AJAX classique (long polling, Server-Sent Events), WebSocket assure une connexion permanente avec des frais généraux minimaux. Pour un développeur PHP, passer des exemples de base de « serveur écho » à une application temps réel industrielle constitue un défi sérieux, lié à la gestion d'état, à la mise à l'échelle et au traitement asynchrone.



Dans cet article, nous examinerons les techniques avancées de travail avec WebSocket en PHP : l'architecture d'un chat multi-utilisateurs, l'intégration avec Redis pour la mise à l'échelle horizontale, le traitement des tâches en arrière-plan et l'optimisation des performances.



1. Architecture d'un serveur WebSocket avancé avec Ratchet



La bibliothèque Ratchet (basée sur ReactPHP) reste la référence pour WebSocket en PHP. Cependant, pour les solutions de production, un simple onMessage ne suffit pas. Examinons une architecture composant avec séparation des responsabilités :



<?phpuse Ratchet\\MessageComponentInterface;use Ratchet\\ConnectionInterface;use React\\EventLoop\\LoopInterface;

class RealTimeHub implements MessageComponentInterface { private $clients; private $loop; private $redis; private $userRegistry;

public function __construct(LoopInterface $loop, \\Redis $redis) { $this->clients = new \\SplObjectStorage; $this->loop = $loop; $this->redis = $redis; $this->userRegistry = []; }

public function onOpen(ConnectionInterface $conn) { $this->clients->attach($conn); echo "Nouvelle connexion : {$conn->resourceId}"; }

public function onMessage(ConnectionInterface $from, $msg) { $data = json_decode($msg, true);

switch ($data['type'] ?? '') { case 'auth': $this->handleAuth($from, $data); break; case 'message': $this->handleMessage($from, $data); break; case 'subscribe': $this->handleSubscribe($from, $data); break; default: $from->send(json_encode(['error' => 'Commande inconnue'])); } }

public function onClose(ConnectionInterface $conn) { $this->clients->detach($conn); // Nettoyage de l'enregistrement utilisateur if (isset($conn->userId)) { unset($this->userRegistry[$conn->userId]); } }

public function onError(ConnectionInterface $conn, \\Exception $e) { $conn->close(); }

private function handleAuth(ConnectionInterface $conn, array $data) { $token = $data['token'] ?? ''; // Vérification du jeton JWT $userId = $this->validateToken($token); if ($userId) { $conn->userId = $userId; $this->userRegistry[$userId] = $conn; $conn->send(json_encode(['type' => 'auth_ok'])); } else { $conn->send(json_encode(['type' => 'auth_fail'])); } }

private function handleMessage(ConnectionInterface $from, array $data) { $targetUserId = $data['to'] ?? null; if ($targetUserId && isset($this->userRegistry[$targetUserId])) { $this->userRegistry[$targetUserId]->send(json_encode([ 'type' => 'message', 'from' => $from->userId ?? 'anonyme', 'text' => $data['text'] ])); } }

private function validateToken(string $token): ?int { // Simulation de vérification JWT $payload = json_decode(base64_decode(explode('.', $token)[1] ?? ''), true); return $payl

Blogs

Book Recommendations