WebSocket Events
Learn how to handle WebSocket events in Sockeon using attribute-based event handlers.
Event System Overview
WebSocket events in Sockeon follow a simple pattern:
- Client sends event → JSON message with
event
anddata
fields - Server routes event → Based on
#[SocketOn]
attributes - Controller handles event → Your business logic
- Server responds → Emit back to client or broadcast to others
Basic Event Handling
Defining Event Handlers
Use the #[SocketOn]
attribute to define event handlers:
use Sockeon\Sockeon\Controllers\SocketController;
use Sockeon\Sockeon\WebSocket\Attributes\SocketOn;
class ChatController extends SocketController
{
#[SocketOn('chat.message')]
public function handleMessage(int $clientId, array $data): void
{
$message = $data['message'] ?? '';
if (empty($message)) {
$this->emit($clientId, 'error', ['message' => 'Message cannot be empty']);
return;
}
// Broadcast to all connected clients
$this->broadcast('chat.message', [
'from' => $clientId,
'message' => $message,
'timestamp' => time()
]);
}
#[SocketOn('user.typing')]
public function handleTyping(int $clientId, array $data): void
{
$isTyping = $data['typing'] ?? false;
// Broadcast typing status to others
$this->broadcast('user.typing', [
'clientId' => $clientId,
'typing' => $isTyping
]);
}
}
Connection Events
Handle special connection events:
use Sockeon\Sockeon\WebSocket\Attributes\OnConnect;
use Sockeon\Sockeon\WebSocket\Attributes\OnDisconnect;
class ConnectionController extends SocketController
{
#[OnConnect]
public function onConnect(int $clientId): void
{
// Called automatically when a client connects
$this->emit($clientId, 'welcome', [
'message' => 'Welcome to the server!',
'clientId' => $clientId
]);
// Notify others about the new connection
$this->broadcast('user.connected', [
'clientId' => $clientId,
'message' => "User {$clientId} joined the server"
]);
}
#[OnDisconnect]
public function onDisconnect(int $clientId): void
{
// Called automatically when a client disconnects
$this->broadcast('user.disconnected', [
'clientId' => $clientId,
'message' => "User {$clientId} left the server"
]);
}
}
Event Naming Conventions
Use hierarchical naming with dots for organization:
class GameController extends SocketController
{
#[SocketOn('game.join')]
public function joinGame(int $clientId, array $data): void
{
$gameId = $data['gameId'] ?? '';
$this->moveClientToNamespace($clientId, "/game/{$gameId}");
$this->emit($clientId, 'game.joined', ['gameId' => $gameId]);
}
#[SocketOn('game.move')]
public function handleMove(int $clientId, array $data): void
{
$move = $data['move'] ?? '';
$this->broadcast('game.move', [
'clientId' => $clientId,
'move' => $move
]);
}
#[SocketOn('game.chat')]
public function handleGameChat(int $clientId, array $data): void
{
$message = $data['message'] ?? '';
$this->broadcast('game.chat', [
'clientId' => $clientId,
'message' => $message
]);
}
}
Event Data Handling
class DataController extends SocketController
{
#[SocketOn('user.update')]
public function updateUser(int $clientId, array $data): void
{
$name = $data['name'] ?? '';
$email = $data['email'] ?? '';
// Validate data
if (empty($name) || empty($email)) {
$this->emit($clientId, 'error', ['message' => 'Name and email are required']);
return;
}
// Update user data
$this->setClientData($clientId, 'name', $name);
$this->setClientData($clientId, 'email', $email);
$this->emit($clientId, 'user.updated', [
'name' => $name,
'email' => $email
]);
}
#[SocketOn('user.info')]
public function getUserInfo(int $clientId, array $data): void
{
$name = $this->getClientData($clientId, 'name');
$email = $this->getClientData($clientId, 'email');
$this->emit($clientId, 'user.info', [
'name' => $name,
'email' => $email
]);
}
}