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

Wrench Laravel Package

chrome-php/wrench

Simple PHP WebSocket library with server and client support. Create a BasicServer, register multiple apps per path, handle incoming data via interfaces, and send responses back to clients. Install via Composer; supports PHP 7.4–8.5.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Install the package:
    composer require chrome-php/wrench
    
  2. Create a basic WebSocket server (e.g., app/Console/Commands/WebSocketServer.php):
    use Wrench\BasicServer;
    use Wrench\Application\DataHandlerInterface;
    use Illuminate\Console\Command;
    
    class WebSocketServer extends Command implements DataHandlerInterface
    {
        protected $signature = 'ws:server';
        protected $description = 'Start the WebSocket server';
    
        public function handle()
        {
            $server = new BasicServer('ws://localhost:8000', [
                'allowed_origins' => ['*'], // Adjust for production
            ]);
    
            $server->registerApplication('chat', $this);
            $server->run();
        }
    
        public function onData(string $data, \Wrench\Connection $connection): void
        {
            $this->info("Received: {$data}");
            $connection->send("Echo: {$data}");
        }
    }
    
  3. Register the command in app/Console/Kernel.php:
    protected $commands = [
        Commands\WebSocketServer::class,
    ];
    
  4. Run the server:
    php artisan ws:server
    
  5. Test with a client (e.g., browser JavaScript):
    const socket = new WebSocket('ws://localhost:8000/chat');
    socket.onopen = () => socket.send('Hello');
    socket.onmessage = (e) => console.log(e.data);
    

First Use Case: Real-Time Chat

  • Use the chat application endpoint to handle messages.
  • Extend DataHandlerInterface to implement custom logic (e.g., broadcast to all connected clients).

Implementation Patterns

Workflows

  1. Server-Side Routing:

    • Register multiple applications under different paths:
      $server->registerApplication('notifications', new NotificationHandler());
      $server->registerApplication('live-updates', new LiveUpdateHandler());
      
    • Use Laravel’s service container to resolve dependencies:
      $server->registerApplication('auth', app(AuthWebSocketHandler::class));
      
  2. Client Management:

    • Track connected clients using a Connection object:
      public function onData(string $data, \Wrench\Connection $connection): void
      {
          $userId = $connection->getExtraData('user_id');
          // Store connection in Redis for later broadcasting
      }
      
    • Use Connection::getExtraData() to attach metadata (e.g., user IDs, session tokens).
  3. Broadcasting:

    • For Laravel integration, use a queue to trigger WebSocket broadcasts:
      // In a Laravel event listener
      event(new MessageSent($message));
      
      // In a queue job
      public function handle()
      {
          $connections = Redis::smembers('ws:connections');
          foreach ($connections as $connectionId) {
              $client = new \Wrench\Client('ws://localhost:8000/chat');
              $client->connect();
              $client->sendData($this->message->data);
              $client->disconnect();
          }
      }
      
  4. Hybrid HTTP/WebSocket:

    • Use Laravel routes to proxy HTTP requests to WebSocket:
      Route::get('/ws-proxy', function () {
          $server = new \Wrench\Client('ws://localhost:8000/chat');
          $server->connect();
          return response()->json(['status' => 'connected']);
      });
      

Integration Tips

  • Logging: Inject a PSR-3 logger for debugging:
    $server->setLogger(app(\Psr\Log\LoggerInterface::class));
    
  • Error Handling: Wrap server startup in a try-catch:
    try {
        $server->run();
    } catch (\Exception $e) {
        report($e);
        $this->error("WebSocket server crashed: " . $e->getMessage());
    }
    
  • Configuration: Store WebSocket settings in config/websocket.php:
    return [
        'port' => env('WEBSOCKET_PORT', 8000),
        'origins' => explode(',', env('WEBSOCKET_ORIGINS', '*')),
    ];
    
    Then load it in your server command:
    $server = new BasicServer("ws://localhost:{$config['port']}", [
        'allowed_origins' => $config['origins'],
    ]);
    

Gotchas and Tips

Pitfalls

  1. Blocking Calls:

    • Avoid synchronous operations (e.g., database queries) in onData(). Use queues or async tasks:
      public function onData(string $data, \Wrench\Connection $connection): void
      {
          dispatch(new ProcessWebSocketData($data, $connection));
      }
      
  2. Connection Leaks:

    • Always close connections explicitly:
      $client->disconnect(); // Critical for resource cleanup
      
    • Use registerShutdownFunction to ensure cleanup on crashes.
  3. Origin Restrictions:

    • Misconfigured allowed_origins will block WebSocket connections. Test with:
      'allowed_origins' => ['http://localhost:3000', 'https://yourdomain.com'],
      
  4. PHP 8.5 Quirks:

    • New: Ensure random_bytes() is available (it is in PHP 8.5, but test if using custom PHP builds).
    • New: Typed properties in DataHandlerInterface may require adjustments if extending classes.
  5. Large Payloads:

    • Wrench has a default payload size limit (65536 bytes). For larger data, implement chunking:
      if (strlen($data) > 65536) {
          $chunks = str_split($data, 65500);
          foreach ($chunks as $chunk) {
              $connection->send($chunk);
          }
      }
      

Debugging

  1. Handshake Failures:

    • Check for missing Sec-WebSocket-Key headers or malformed responses. Enable verbose logging:
      $server->setLogger(new \Monolog\Logger('wrench', [
          new \Monolog\Handler\StreamHandler(storage_path('logs/wrench.log'), \Monolog\Logger::DEBUG),
      ]));
      
  2. Connection Timeouts:

    • Increase PHP’s max_execution_time or use a process manager (e.g., Supervisor) to restart crashed servers.
  3. Memory Leaks:

    • Monitor memory usage with memory_get_usage(). Close idle connections:
      $connection->closeIfIdle(30); // Close after 30 seconds of inactivity
      

Extension Points

  1. Custom Handshake:

    • Extend \Wrench\Server to validate tokens or enforce auth:
      class AuthServer extends \Wrench\BasicServer
      {
          protected function onHandshake(\Wrench\Connection $connection): void
          {
              $token = $connection->getHeader('Authorization');
              if (!auth()->validateToken($token)) {
                  $connection->close();
                  return;
              }
              parent::onHandshake($connection);
          }
      }
      
  2. STOMP Support:

    • Use Wrench’s built-in STOMP adapter for pub/sub:
      $stompServer = new \Wrench\StompServer('ws://localhost:8000/stomp');
      $stompServer->registerApplication('queue', new StompHandler());
      
  3. Laravel Service Provider:

    • Create a provider to manage the WebSocket server lifecycle:
      class WebSocketServiceProvider extends ServiceProvider
      {
          public function register()
          {
              $this->app->singleton(WebSocketServer::class, function () {
                  $server = new BasicServer(config('websocket.url'), config('websocket.options'));
                  return $server;
              });
          }
      }
      
  4. Metrics:

    • Integrate with Laravel Horizon or Prometheus:
      $server->onConnection(function (\Wrench\Connection $connection) {
          app(\App\Metrics\WebSocketMetrics::class)->incrementConnections();
      });
      

Tips

  • Use reactphp for Async:

    • Leverage ReactPHP’s event loop for non-blocking operations:
      use React\EventLoop\Factory;
      
      $loop = Factory::create();
      $server = new \Wrench\BasicServer('ws://localhost:8000', [], $loop);
      $loop->run();
      
  • Load Testing:

    • Use tools like websocat or autobahn-testsuite to simulate traffic:
      websocat ws://localhost:8000/chat
      
  • Docker Integration:

    • Run Wrench in a separate container with a health check:
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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