Installation:
composer require gos/web-socket-bundle
Add to config/bundles.php:
return [
// ...
Gos\WebSocketBundle\GosWebSocketBundle::class => ['all' => true],
];
Configure WebSocket Server:
Update config/packages/gos_web_socket.yaml:
gos_web_socket:
server:
port: 8080
host: 0.0.0.0
clients_max: 1000
routing:
default_route: 'app.websocket.default'
First Use Case: Create a WebSocket route in a controller:
use Gos\Bundle\WebSocketBundle\Annotation\Route;
use Gos\Bundle\WebSocketBundle\Annotation\WebSocket;
class ChatController
{
/**
* @Route("/chat", name="app.websocket.chat")
* @WebSocket("chat")
*/
public function onChatConnection(\Gos\Bundle\WebSocketBundle\WebSocket\ClientInterface $client)
{
$client->send(json_encode(['type' => 'connection', 'message' => 'Welcome!']));
}
}
Run the Server:
php bin/console gos:websocket:start
Test with JavaScript:
const socket = new WebSocket('ws://localhost:8080/chat');
socket.onmessage = (event) => console.log(event.data);
Real-Time Messaging:
@WebSocket annotations to define event handlers for connection, message, and disconnection./**
* @WebSocket("chat.message")
*/
public function onChatMessage(\Gos\Bundle\WebSocketBundle\WebSocket\ClientInterface $client, $data)
{
$message = json_decode($data, true);
$this->broadcastToAll('chat', json_encode(['type' => 'message', 'content' => $message['content']]));
}
Broadcasting to Specific Clients:
$this->broadcastTo(['client_id_1', 'client_id_2'], 'chat', json_encode(['type' => 'alert']));
Authentication:
/**
* @Route("/private-chat/{token}", name="app.websocket.private_chat")
* @WebSocket("private_chat")
*/
public function onPrivateChat(\Gos\Bundle\WebSocketBundle\WebSocket\ClientInterface $client, $token)
{
if (!$this->validateToken($token)) {
$client->close();
return;
}
// Proceed...
}
Integration with Symfony Events:
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
public function __construct(private EventDispatcherInterface $dispatcher) {}
/**
* @WebSocket("chat.connection")
*/
public function onConnection(\Gos\Bundle\WebSocketBundle\WebSocket\ClientInterface $client)
{
$this->dispatcher->dispatch(new WebSocketConnectionEvent($client));
}
Frontend Integration:
import { WebSocket } from 'autobahnjs';
const connection = new WebSocket('ws://localhost:8080/chat');
connection.onopen = () => connection.send(JSON.stringify({ type: 'join', user: 'Alice' }));
Load Balancing:
location /ws {
proxy_pass http://websocket_server:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
Scaling:
Testing:
Gos\Bundle\WebSocketBundle\Tests\WebSocketTestCase for unit/integration tests:
public function testChatConnection()
{
$client = $this->createMockClient();
$this->assertSame('Welcome!', $this->getController()->onChatConnection($client));
}
CORS Issues:
cors option in the bundle config:
gos_web_socket:
server:
cors_origin: ["http://localhost:3000"]
Connection Limits:
clients_max is 1000. Increase if needed, but monitor memory usage:
gos_web_socket:
server:
clients_max: 5000
PHP-FPM vs. CLI:
pdo_mysql).Route Conflicts:
ws.chat).Memory Leaks:
$client->setTimeout(30); // Close after 30 seconds of inactivity
Logs:
gos_web_socket.yaml:
gos_web_socket:
debug: true
var/log/gos_websocket.log.Common Errors:
Connection refused: Verify the port is open and not blocked by a firewall.Invalid route: Ensure the route is annotated with @WebSocket and matches the bundle config.JSON decode error: Validate payloads on the client side before sending.Tooling:
tcpdump or Wireshark to inspect WebSocket traffic:
tcpdump -i any port 8080 -w websocket.pcap
Custom Handshake:
Gos\Bundle\WebSocketBundle\WebSocket\Server\Server:
class CustomServer extends Server
{
protected function onHandshake($resource, $key)
{
// Custom logic (e.g., validate API keys)
return parent::onHandshake($resource, $key);
}
}
services.yaml:
services:
Gos\Bundle\WebSocketBundle\WebSocket\Server\Server:
class: App\WebSocket\CustomServer
Middleware:
use Gos\Bundle\WebSocketBundle\WebSocket\MiddlewareInterface;
class AuthMiddleware implements MiddlewareInterface
{
public function onMessage(\Gos\Bundle\WebSocketBundle\WebSocket\ClientInterface $client, $message)
{
if (!$this->isAuthenticated($message)) {
$client->close();
}
return $message;
}
}
services.yaml:
services:
Gos\Bundle\WebSocketBundle\WebSocket\Middleware\AuthMiddleware:
tags: ['gos_websocket.middleware']
Event Subscribers:
use Gos\Bundle\WebSocketBundle\Event\WebSocketEvent;
class WebSocketSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
WebSocketEvent::CONNECTION => 'onConnection',
WebSocketEvent::MESSAGE => 'onMessage',
];
}
public function onConnection(WebSocketEvent $event) { /* ... */ }
}
Custom Protocols:
class CustomProtocol extends \Gos\Bundle\WebSocketBundle\WebSocket\Protocol\Protocol
{
public function encode($data) { /* ... */ }
public function decode($data) { /* ... */ }
}
services.yaml:
services:
Gos\Bundle\WebSocketBundle\WebSocket\Protocol\Protocol:
class: App\WebSocket\Custom
How can I help you explore Laravel packages today?