SocketIO
SocketIO связывает PHP-сервер и клиентские приложения именованными событиями. Поверх Engine transport находятся namespaces, sockets, rooms, acknowledgements и adapter рассылки.
Это не обычный WebSocket echo-server: события имеют собственный envelope поверх Engine packets. Клиент new WebSocket(url) без этого слоя не заменяет Socket.IO-клиент.
Подключение
Заголовок раздела «Подключение»composer config repositories.localzet-socketio vcs https://github.com/localzet/SocketIOcomposer require localzet/socketio:dev-mainМанифест требует PHP 8.1+, Server ^4.1 и localzet/channel ^1.0 || ^2.0. Multi-worker adapter обращается к \Channel\Client; соседний Tunnel не является автоматической заменой этого контракта.
Listener и событие
Заголовок раздела «Listener и событие»use localzet\Server;use localzet\SocketIO\SocketIO;
require __DIR__ . '/vendor/autoload.php';
$io = new SocketIO();$worker = new Server('SocketIO://127.0.0.1:2020');$worker->count = 1;$io->attach($worker);
$io->on('connection', static function ($socket): void { $socket->on('message', static function ($message) use ($socket): void { $socket->emit('reply', ['received' => $message]); });});
Server::runAll();SocketIO без port регистрирует protocol alias, но не открывает listener. Это позволяет указать bind явно. new SocketIO(2020) создаёт listener на 0.0.0.0:2020.
JS-клиент должен реализовывать совместимые Engine и Socket.IO wire protocols. Наличие emit/on не подтверждает совместимость с последней major-версией npm socket.io-client. Проверяйте handshake, polling/upgrade и формат событий конкретной версии клиента.
Namespaces
Заголовок раздела «Namespaces»$orders = $io->of('/orders');$orders->on('connection', static function ($socket): void { $socket->emit('hello', ['namespace' => '/orders']);});Namespace отделяет sockets и события. of('orders') добавит /; повторный вызов вернёт существующий объект. Namespace не проверяет право пользователя на операцию.
$io->on/emit/to/in делегируются корневому /. Для другого пространства вызывайте методы объекта, полученного через of().
$socket->join('order:42');$orders->to('order:42')->emit('updated', ['id' => 42]);$socket->to('order:42')->emit('updated', ['id' => 42]);$socket->leave('order:42');Namespace broadcast включает отправителя, если он входит в выборку. Broadcast от socket исключает его самого. Rooms — выборка получателей, а не проверка доступа: подтверждайте право до join и до выполнения входящего действия.
Выбор rooms/flags сбрасывается после пользовательского emit. Не сохраняйте builder, ожидая неизменного фильтра.
Последний callable в $socket->emit() регистрируется как acknowledgement callback с ID пакета. Для room/broadcast callbacks не поддерживаются и вызывают исключение.
ACK означает ответ клиентского обработчика, не транзакционный commit. Отдельного timeout/retry-контракта для каждого ACK здесь нет. Срок ожидания бизнес-ответа должен ограничивать код приложения.
Lifecycle
Заголовок раздела «Lifecycle»$socket->disconnect(false) отключает socket namespace; true закрывает целое client connection. После закрытия удаляются локальные memberships.
Новое подключение не восстанавливает автоматически доверенную identity и разрешённые rooms прежнего пользователя. Их нужно установить заново через прикладную авторизацию.
Несколько worker
Заголовок раздела «Несколько worker»DefaultAdapter хранит rooms и socket IDs в памяти процесса. Увеличение count не добавляет доставку другим worker.
ChannelAdapter использует \Channel\Client и отдельный Channel-сервер. Общий broadcast transport и sticky routing для long polling — разные задачи; наличие adapter не подтверждает корректную маршрутизацию session-запросов балансировщиком.
Origins и handshake
Заголовок раздела «Origins и handshake»Default origins — *:*. Установите origin policy браузерного приложения и независимо проверяйте identity/permissions. Origin не является аутентификацией.
Handshake содержит headers, address, query и время. Это metadata соединения, не verified user claims. Не используйте query-токен как бессрочный секрет и не включайте отладочный вывод на приватных событиях.
API объектов, adapters и Engine
Исходный код · AGPL-3.0