Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Websocket Laravel Package

phrity/websocket

PHP WebSocket client and multi-connection server with ws/wss support. Includes listener callbacks, standard Close and Ping/Pong handling, optional deflate compression, fragmentation and masking support, plus middleware system for extending behavior.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require phrity/websocket
    
  2. Basic Client Usage (Request/Response):

    use WebSocket\Client;
    
    $client = new Client("wss://echo.websocket.org/");
    $client
        ->addMiddleware(new \WebSocket\Middleware\CloseHandler())
        ->addMiddleware(new \WebSocket\Middleware\PingResponder());
    
    $client->text("Hello");
    $response = $client->receive();
    echo $response->getContent(); // Output: "Hello"
    $client->close();
    
  3. Basic Server Usage (Continuous Listening):

    use WebSocket\Server;
    
    $server = new Server();
    $server
        ->addMiddleware(new \WebSocket\Middleware\CloseHandler())
        ->addMiddleware(new \WebSocket\Middleware\PingResponder())
        ->onText(function ($server, $connection, $message) {
            $connection->text("Echo: " . $message->getContent());
        });
    
    $server->start();
    

First Use Case: Real-Time Chat

  • Use the Server to handle multiple connections.
  • Use the Client for user-specific connections (e.g., admin dashboard).
  • Leverage middleware for automatic ping/pong and graceful disconnections.

Implementation Patterns

Client Patterns

  1. Request/Response Workflow:

    $client = new Client("wss://api.example.com/ws");
    $client->text(json_encode(['action' => 'fetch_data']));
    $response = $client->receive(); // Blocking call
    $data = json_decode($response->getContent(), true);
    
  2. Event-Driven Subscription:

    $client = new Client("wss://stream.example.com");
    $client->onText(function ($client, $connection, $message) {
        $data = json_decode($message->getContent(), true);
        // Process real-time updates
    });
    $client->start(); // Non-blocking
    
  3. Reconnection Logic:

    $client = new Client("wss://reliable.example.com");
    $client->onError(function ($client, $connection, $error) {
        if ($error instanceof \WebSocket\Exception\ReconnectException) {
            $client->reconnect();
        }
    });
    

Server Patterns

  1. Multi-Connection Handling:

    $server = new Server();
    $server->onText(function ($server, $connection, $message) {
        $connection->text("Processed: " . $message->getContent());
    });
    $server->start();
    
  2. Connection-Specific Logic:

    $server = new Server();
    $server->onOpen(function ($server, $connection) {
        $connection->setMeta(['user_id' => 123]);
    });
    $server->onText(function ($server, $connection, $message) {
        $userId = $connection->getMeta('user_id');
        // Apply user-specific logic
    });
    
  3. Middleware Stack:

    $server = new Server();
    $server
        ->addMiddleware(new \WebSocket\Middleware\CloseHandler())
        ->addMiddleware(new \WebSocket\Middleware\PingResponder())
        ->addMiddleware(new \WebSocket\Middleware\CompressionHandler());
    

Integration with Laravel

  1. Service Provider Setup:

    // app/Providers/WebSocketServiceProvider.php
    public function register()
    {
        $this->app->singleton(\WebSocket\Server::class, function ($app) {
            $server = new \WebSocket\Server();
            $server->onText([$this->app['websocket.handler'], 'handle']);
            return $server;
        });
    }
    
  2. Event-Driven Controllers:

    // app/Http/Controllers/WebSocketController.php
    public function handle($server, $connection, $message)
    {
        $data = json_decode($message->getContent(), true);
        // Dispatch Laravel events or queue jobs
        event(new WebSocketMessageReceived($data));
    }
    
  3. Broadcasting with Laravel Echo:

    // resources/js/bootstrap.js
    import Echo from 'laravel-echo';
    window.Pusher = require('pusher-js');
    window.Echo = new Echo({
        broadcaster: 'websocket',
        wsHost: window.location.hostname,
        wsPort: 6001,
        forceTLS: false,
        enabledTransports: ['ws', 'wss'],
    });
    

Gotchas and Tips

Common Pitfalls

  1. Blocking Calls:

    • Client::receive() is blocking. Use onText for non-blocking workflows.
    • Fix: Offload blocking operations to queues or use start() for event-driven logic.
  2. Middleware Order:

    • Middleware runs in registration order. Place CloseHandler first to ensure graceful shutdowns.
    • Fix: Reorder middleware if unexpected behavior occurs.
  3. Connection Leaks:

    • Forgetting to call $client->close() or $server->shutdown() can leak resources.
    • Fix: Use try-finally blocks or Laravel's illuminate/support for cleanup:
      try {
          $client->start();
      } finally {
          $client->close();
      }
      
  4. SSL/TLS Issues:

    • wss:// requires valid certificates. Self-signed certs may fail silently.
    • Fix: Use stream_context_create for custom CA paths:
      $context = stream_context_create([
          'ssl' => ['verify_peer' => false, 'allow_self_signed' => true],
      ]);
      $client = new Client("wss://localhost", [], $context);
      
  5. Fragmented Messages:

    • Large messages may be fragmented. Ensure your onText handler can handle partial data.
    • Fix: Use Message::isFinalFragment() to check completeness.

Debugging Tips

  1. Logging:

    • Enable PSR-3 logging via setLogger:
      $logger = new \Monolog\Logger('websocket');
      $client->setLogger($logger);
      
    • Log middleware execution for debugging:
      $client->addMiddleware(new \WebSocket\Middleware\LoggingMiddleware($logger));
      
  2. Connection Identity:

    • Use Connection::getIdentity() to track connections (v3.7+):
      $server->onOpen(function ($server, $connection) {
          $identity = $connection->getIdentity();
          // Store in database or cache
      });
      
  3. Timeouts:

    • Set timeouts during start() to avoid hanging:
      $client->start(5.0); // 5-second timeout
      

Extension Points

  1. Custom Middleware:

    namespace App\Middleware;
    
    use WebSocket\Middleware\MiddlewareInterface;
    
    class AuthMiddleware implements MiddlewareInterface
    {
        public function __invoke($next)
        {
            return function ($client, $connection, $message) use ($next) {
                if (!$this->validateToken($message->getContent())) {
                    $connection->close(1008, "Unauthorized");
                    return;
                }
                return $next($client, $connection, $message);
            };
        }
    
        private function validateToken(string $content): bool { /* ... */ }
    }
    

    Register it:

    $client->addMiddleware(new \App\Middleware\AuthMiddleware());
    
  2. PSR-15 Middleware:

    • Use Nyholm\PsrHttp\Factory\Psr17Factory for PSR-15 compatibility:
      $httpFactory = new \Nyholm\PsrHttp\Factory\Psr17Factory();
      $client = new \WebSocket\Client("wss://example.com", [], [], $httpFactory);
      
  3. Custom Identity:

    • Implement \WebSocket\Identity\IdentityInterface for connection tracking:
      class UserIdentity implements IdentityInterface
      {
          public function getId(): string { return $this->userId; }
      }
      
    • Attach to connections:
      $connection->setIdentity(new UserIdentity($userId));
      

Laravel-Specific Quirks

  1. Queue Integration:

    • Dispatch jobs in onText to avoid blocking:
      $server->onText(function ($server, $connection, $message) {
          dispatch(new ProcessWebSocketMessage($message->getContent()));
      });
      
  2. Artisan Commands:

    • Run the WebSocket server as a background process:
      // app/Console/Commands/StartWebSocket.php
      public function handle()
      {
          $server = resolve(\WebSocket\Server::class);
          $server->start();
      }
      
    • Schedule with Laravel Scheduler:
      $schedule->command('websocket:start')->daily();
      
  3. **Route Caching

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor