You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PHP对接Socket.IO?Node.js转PHP及Laravel适配诉求

Converting Node.js Socket.IO + RabbitMQ to Laravel/PHP

Hey there! Let's tackle converting your Node.js Socket.IO + RabbitMQ setup to Laravel/PHP. First, a quick heads-up: PHP isn't natively event-driven like Node.js, so we'll need to use an async PHP library that supports the Socket.IO protocol. My go-to here is workerman/php-socket.io—it's a solid implementation that plays nicely with Laravel.

Step 1: Install Dependencies

First, add the required packages to your Laravel project:

composer require workerman/php-socket.io php-amqplib/php-amqplib
  • workerman/php-socket.io: Implements the Socket.IO server in PHP
  • php-amqplib/php-amqplib: PHP client for RabbitMQ

Step 2: Create an Artisan Command for the Socket.IO Server

We'll build a custom Artisan command to manage our Socket.IO server (this makes it easy to start/stop the service within Laravel).

Run this to generate the command skeleton:

php artisan make:command SocketIOServer

Replace the generated app/Console/Commands/SocketIOServer.php with this code:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Workerman\Worker;
use Workerman\SocketIO\SocketIO;
use PhpAmqpLib\Connection\AMQPStreamConnection;

class SocketIOServer extends Command
{
    protected $signature = 'socket:serve';
    protected $description = 'Start Socket.IO server to broadcast RabbitMQ messages to frontend';

    public function handle()
    {
        // Initialize Socket.IO server on port 2021 (adjust port as needed)
        $io = new SocketIO(2021);

        // Track connected clients (optional, useful for debugging)
        $connectedClients = [];

        // Handle new client connections
        $io->on('connection', function ($socket) use (&$connectedClients) {
            $this->info("New client connected: {$socket->id}");
            $connectedClients[$socket->id] = $socket;

            // Handle client disconnection
            $socket->on('disconnect', function () use ($socket, &$connectedClients) {
                $this->info("Client disconnected: {$socket->id}");
                unset($connectedClients[$socket->id]);
            });
        });

        // Connect to RabbitMQ (match your Node.js credentials)
        try {
            $rabbitConnection = new AMQPStreamConnection(
                'x.x.x.x',       // RabbitMQ host
                1234,            // RabbitMQ port
                'your_username', // RabbitMQ username
                'your_password'  // RabbitMQ password
            );
            $channel = $rabbitConnection->channel();

            // Declare the queue (matches your Node.js queue name '1')
            $queueName = '1';
            $channel->queue_declare($queueName, false, true, false, false);
            $channel->queue_bind($queueName, '', '#'); // Bind to all routing keys

            // Consume messages from RabbitMQ
            $messageCallback = function ($msg) use ($io) {
                // Parse the message (match your Node.js message structure)
                $rawMessage = json_decode($msg->body, true);
                $messageData = $rawMessage['data']['data'] ?? $rawMessage;

                $this->info("Broadcasting message: " . json_encode($messageData));
                // Send message to all connected Socket.IO clients
                $io->emit('message-name', $messageData);
            };

            $channel->basic_consume($queueName, '', false, true, false, false, $messageCallback);

            // Run RabbitMQ consumer in a separate worker
            $rabbitWorker = new Worker();
            $rabbitWorker->onWorkerStart = function () use ($channel) {
                while ($channel->is_consuming()) {
                    $channel->wait();
                }
            };

            // Start all workers
            Worker::runAll();

        } catch (\Exception $e) {
            $this->error("RabbitMQ connection failed: " . $e->getMessage());
        }
    }
}

Step 3: Adjust Frontend Code

Update your HTML to connect to the PHP Socket.IO server (note the port change to 2021):

<!DOCTYPE html>
<html>
<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
    <script>
        (function () {
            const onMessage = (data) => {
                console.log('Received message:', data);
            };

            var connectToServer = function () {
                // Connect to PHP Socket.IO server
                var socket = io.connect('http://localhost:2021');
                socket.on('message-name', onMessage);
                
                // Optional: Add connection status logging
                socket.on('connect', () => console.log('Connected to PHP Socket.IO server'));
                socket.on('disconnect', () => console.log('Disconnected from server'));
            };

            connectToServer();
        })();
    </script>
</head>
<body>
</body>
</html>

Step 4: Start the Server

Run the Artisan command to launch your Socket.IO server:

php artisan socket:serve

Key Notes & Fixes from Your Original Node.js Code

  • I fixed a bug in your original Node.js code: you had io.sockets.on('connection') inside the RabbitMQ message callback, which would re-bind the connection event every time a message arrived (causing duplicate events). The PHP version handles client connections once, outside the message consumer.
  • Ensure the RabbitMQ credentials, host, port, and queue name match exactly what you used in Node.js.
  • Make sure port 2021 is open in your firewall and not used by another service.
  • If you need to push messages from other parts of your Laravel app (e.g., controllers), you can use Workerman's remote push feature (refer to their official docs for implementation details).

内容的提问来源于stack exchange,提问作者Jaydeep Charadva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:01:23