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

Ws Server Bundle Laravel Package

codememory/ws-server-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require codememory/ws-server-bundle
    

    Ensure Codememory\WebSocketServerBundle\WebSocketServerBundle::class is registered in config/bundles.php.

  2. Basic Configuration (config/packages/codememory_websocket_server.yaml):

    codememory_websocket_server:
        server:
            adapter: "Swoole"
            host: "0.0.0.0"  # Expose to LAN if needed
            port: 8079
    
  3. First Use Case:

    • Create a simple event listener to handle incoming messages:
      // src/WebSocket/EventListeners/TestHandler.php
      namespace App\WebSocket\EventListeners;
      
      use Codememory\WebSocketServerBundle\Interfaces\MessageEventListenerInterface;
      use Codememory\WebSocketServerBundle\Interfaces\MessageInterface;
      
      class TestHandler implements MessageEventListenerInterface
      {
          public function handle(MessageInterface $message)
          {
              $data = json_decode($message->getData(), true);
              // Process $data (e.g., broadcast to clients)
              $message->send('ACK: ' . json_encode($data));
          }
      }
      
    • Register the listener in config:
      codememory_websocket_server:
          event_listeners:
              - { event: "TEST", listener: "App\WebSocket\EventListeners\TestHandler" }
      
  4. Start the Server:

    php bin/console codememory:websocket:server:start
    

    Test with a WebSocket client (e.g., browser JS or wscat):

    wscat -c ws://localhost:8079
    > {"event": "TEST", "data": {"test": "payload"}}
    

Implementation Patterns

Core Workflows

  1. Event-Driven Architecture:

    • Listener Registration: Define listeners in config/packages/codememory_websocket_server.yaml under event_listeners. Example for multiple events:
      event_listeners:
          - { event: "CHAT_MESSAGE", listener: "App\WebSocket\ChatHandler" }
          - { event: "AUTH", listener: "App\WebSocket\AuthHandler" }
      
    • Handler Structure: Implement MessageEventListenerInterface:
      class ChatHandler implements MessageEventListenerInterface
      {
          public function handle(MessageInterface $message)
          {
              $this->broadcastToRoom($message->getData(), $message->getClientId());
          }
      }
      
  2. Client Management:

    • Sending Messages: Use $message->send() to reply to a client or $message->broadcast() to send to all.
      $message->send(json_encode(['status' => 'success']));
      
    • Client-Specific Logic: Access client ID via $message->getClientId() for targeted actions.
  3. Integration with Laravel:

    • Dependency Injection: Inject WebSocketServer service into controllers/services:
      use Codememory\WebSocketServerBundle\WebSocketServer;
      
      class ChatController
      {
          public function __construct(private WebSocketServer $wsServer) {}
      
          public function sendNotification()
          {
              $this->wsServer->broadcast('NOTIFICATION', ['message' => 'Hello!']);
          }
      }
      
    • Middleware: Use Laravel middleware to validate/authenticate WebSocket connections (e.g., via onOpen in Swoole).
  4. Configuration Overrides:

    • Dynamic Port/Host: Override defaults via environment variables or runtime config:
      # config/packages/codememory_websocket_server.yaml
      server:
          host: "%env(WSS_HOST)%"
          port: "%env(int:WSS_PORT, 8079)%"
      
  5. Scaling:

    • Multiple Instances: Use Redis/PubSub for cross-server communication if running multiple WebSocket servers.
    • Load Balancing: Deploy behind a reverse proxy (e.g., Nginx) with sticky sessions for client persistence.

Integration Tips

  1. Frontend Integration:

    • Use libraries like Socket.IO (with fallback) or native WebSocket API:
      const socket = new WebSocket('ws://localhost:8079');
      socket.onmessage = (event) => console.log(JSON.parse(event.data));
      socket.send(JSON.stringify({ event: "TEST", data: { foo: "bar" } }));
      
  2. Authentication:

    • Implement a custom onOpen handler in Swoole config to validate tokens:
      codememory_websocket_server:
          config:
              swoole:
                  onOpen: App\WebSocket\SwooleEventHandlers::onOpen
      
      // App\WebSocket\SwooleEventHandlers
      class SwooleEventHandlers
      {
          public static function onOpen($server, $request)
          {
              $token = $request->get['token'];
              if (!self::validateToken($token)) {
                  $server->close($request->fd);
              }
          }
      }
      
  3. Logging:

    • Extend the MessageInterface to log events:
      $logger = app(\Psr\Log\LoggerInterface::class);
      $logger->info('WebSocket event', ['event' => $message->getEvent(), 'data' => $message->getData()]);
      
  4. Testing:

    • Use PHPUnit with ReactPHP or Guzzle to mock WebSocket connections:
      $client = new \React\Socket\Connection('ws://localhost:8079');
      $client->send(json_encode(['event' => 'TEST']));
      

Gotchas and Tips

Pitfalls

  1. Swoole Dependencies:

    • Missing Extension: Ensure ext-swoole is installed (pecl install swoole). The bundle will not work without it.
      sudo apt-get install php-swoole  # Debian/Ubuntu
      
    • PHP Version: Swoole 5.x+ requires PHP 7.4+. Check compatibility with your Laravel version.
  2. Configuration Overrides:

    • YAML vs. PHP Config: If using config/bundles.php, ensure the bundle is not auto-registered by Flex to avoid conflicts.
    • Default Values: The config key in YAML is not merged with defaults—explicitly define all Swoole settings:
      config:
          swoole:
              worker_num: 8
              task_worker_num: 4
      
  3. Event Naming:

    • Case Sensitivity: Event names in listeners must match exactly (e.g., "TEST" vs. "test"). Use constants for consistency:
      class EventNames {
          public const CHAT = 'CHAT_MESSAGE';
      }
      
  4. Connection Management:

    • Memory Leaks: Swoole workers are long-lived. Avoid storing large data in global variables.
    • Client Disconnections: Handle onClose in Swoole config to clean up resources:
      config:
          swoole:
              onClose: App\WebSocket\SwooleEventHandlers::onClose
      
  5. Cross-Origin Issues:

    • CORS: Swoole does not handle CORS by default. Use middleware or a proxy (e.g., Nginx) to add headers:
      location /ws/ {
          proxy_pass http://localhost:8079;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          proxy_set_header Host $host;
          add_header 'Access-Control-Allow-Origin' '*';
      }
      

Debugging

  1. Logs:

    • Enable Swoole logging via config:
      config:
          swoole:
              log_file: "/var/log/swoole.log"
              log_level: 7  # DEBUG
      
    • Check Laravel logs for listener errors (storage/logs/laravel.log).
  2. Common Errors:

    • Class not found: Ensure listeners are autoloaded (run composer dump-autoload).
    • Port in Use: Change the port or kill the existing process (lsof -i :8079).
    • Serialization Errors: Validate JSON payloads in listeners:
      try {
          $data = json_decode($message->getData(), true);
      } catch (\Throwable $e) {
          $message->send(json_encode(['error' => 'Invalid payload']));
      }
      
  3. Development Workflow:

    • Hot Reloading: Restart the server after config/listener changes:
      php bin/console codememory:websocket:server:restart
      
    • Docker: Use swoole:alpine images and expose ports correctly:
      RUN pe
      
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.
datacore/hub-sdk
alengo/sulu-http-cache-bundle
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable
irajul/filament-shadcn-theme
agtp/agtp-php
agtp/mod-php
centraldesktop/protobuf-php
trappistes/laravel-custom-fields
splash/sonata-admin
splash/metadata