承接 sfcod/socketio 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

sfcod/socketio

Composer 安装命令:

composer require sfcod/socketio

包简介

SocketIo adapter for Symfony

README 文档

README

Scrutinizer Code QualityCode Climate

Use all power of socket.io in your Symfony project.

Config

Install node, after install npm
    npm install --prefix ./vendor/sfcod/socketio/Server
services:
    App\SocketIo\:
        resource: '../src/SocketIo/*'
        tags: ['sfcod.socketio.event']
        # If you want override default JoinHandler/LeaveHandler. For example, add some condition for join/leave a room.
        exclude:
            - '../src/SocketIo/JoinHandler.php' # Optional
            - '../src/SocketIo/LeaveHandler.php' # Optional
        
  
    # If you want override default JoinHandler
    SfCod\SocketIoBundle\Service\JoinHandler:
        class: App\SocketIo\JoinHandler
        tags: ['sfcod.socketio.event']

    # If you want override default LeaveHandler
    SfCod\SocketIoBundle\Service\LeaveHandler:
        class: App\SocketIo\LeaveHandler
        tags: ['sfcod.socketio.event']

Extend base class or use SF decorator. Ovveride fire or handle methods if it needs.

namespace App\SocketIo;

use SfCod\SocketIoBundle\Service\JoinHandler as JoinHandlerBase;

class JoinHandler extends JoinHandlerBase
{
    public function fire(): array
    {
        // Some additional logic here.
        // ... 
        return array_merge_recursive(parent::fire(), [
            'key' => 'value'
        ]);
    }
}
Process Middlewares

If you use doctrine, then you can connect "doctrine reconnect", then it will be reconnect for each process.

sfcod_socketio:
    processMiddlewares:
        - 'SfCod\SocketIoBundle\Middleware\Process\DoctrineReconnect'
###> socketio config ###
SOCKET_IO_WS_SERVER=localhost:1358
SOCKET_IO_WS_CLIENT=localhost:1358
SOCKET_IO_SSL='' || '{"key":"path to key", "cert":"path to cert"}'
SOCKET_IO_NSP=redis
###< socketio config ###

JWT token auth. Put SOCKET_IO_AUTH_TOKEN_PATH OR SOCKET_IO_AUTH_TOKEN_VALUE

#Public jwt token key path (Will be join with base path)
SOCKET_IO_AUTH_TOKEN_PATH='/config/jwt/public.pem'
#Public key value
SOCKET_IO_AUTH_TOKEN_VALUE='public key value'
#You can change token name. Default name is 'token'
SOCKET_IO_AUTH_TOKEN_NAME='token'
    var socket = io('{your_host_address}:1367/notifications',  {
        query: {
            token: 'yourTokenHere',
        },
     });

Usage

Start nodejs server
    php bin/console socket-io:node-js-server
Start php server
    php bin/console socket-io:php-server
Create publisher from server to client
    use SfCod\SocketIoBundle\Events\EventInterface;
    use SfCod\SocketIoBundle\Events\EventPublisherInterface;
    use SfCod\SocketIoBundle\Events\AbstractEvent;
    
    class CountEvent extends AbstractEvent implements EventInterface, EventPublisherInterface
    {
        /**
         * Changel name. For client side this is nsp.
         */
        public static function broadcastOn(): array
        {
            return ['notifications'];
        }
    
        /**
         * Event name
         */
        public static function name(): string
        {
            return 'update_notification_count';
        }
            
        /**
         * Emit client event
         * @return array
         */
        public function fire(): array
        {
            return [
                'count' => 10,
            ];
        }
    }
    var socket = io('{your_host_address}:1367/notifications');
    socket.on('update_notification_count', function(data){
        console.log(data)
    });
Create receiver from client to server
    use SfCod\SocketIoBundle\Events\EventInterface;
    use SfCod\SocketIoBundle\Events\EventSubscriberInterface;
    use SfCod\SocketIoBundle\Events\AbstractEvent;
    use SfCod\SocketIoBundle\Service\Broadcast;

    class MarkAsReadEvent extends AbstractEvent implements EventInterface, EventSubscriberInterface
    {

        private $broadcast;
    
        public function __construct(Broadcast $broadcast)
        {
            $this->broadcast = $broadcast;
        }

        /**
         * Changel name. For client side this is nsp.
         */
        public static function broadcastOn(): array
        {
            return ['notifications'];
        }
    
        /**
         * Event name
         */
        public static function name(): string
        {
            return 'mark_as_read_notification';
        }
            
        /**
         * Handle client event
         */
        public function handle()
        {
            // Mark notification as read
            // And call client update
            $this->broadcast->emit('update_notification_count', ['some key' => 'some value']);
        }
    }
    var socket = io('{your_host_address}:1367/notifications');
    socket.emit('mark_as_read_notification', {id: 10});

You can have publisher and receiver in one event. If you need check data from client to server you should use:

  • EventPolicyInterface
Receiver with checking from client to server
    use SfCod\SocketIoBundle\Events\EventSubscriberInterface;
    use SfCod\SocketIoBundle\Events\EventInterface;
    use SfCod\SocketIoBundle\Events\EventPolicyInterface;
    use SfCod\SocketIoBundle\Events\AbstractEvent;
    use SfCod\SocketIoBundle\Service\Broadcast;

    class MarkAsReadEvent extends AbstractEvent implements EventInterface, EventSubscriberInterface, EventPolicyInterface
    {

        private $broadcast;
    
        public function __construct(Broadcast $broadcast)
        {
            $this->broadcast = $broadcast;
        }

        /**
         * Changel name. For client side this is nsp.
         */
        public static function broadcastOn(): array
        {
            return ['notifications'];
        }
    
        /**
         * Event name
         */
        public static function name(): string
        {
            return 'mark_as_read_notification';
        }
         
        public function can($data): bool
        {
            // Check data from client    
            return true;
        }        
        
        /**
         * Emit client event
         * @return array
         */
        public function handle()
        {
            // Mark notification as read
            // And call client update
            $this->broadcast->emit('update_notification_count', ['some key' => 'some value']);
        }
    }

Socket.io rooms

  • EventRoomInterface (Backend side)
    use SfCod\SocketIoBundle\Events\EventPublisherInterface;
    use SfCod\SocketIoBundle\Events\EventInterface;
    use SfCod\SocketIoBundle\Events\EventRoomInterface;
    use SfCod\SocketIoBundle\Events\AbstractEvent;

    class CountEvent extends AbstractEvent implements EventInterface, EventPublisherInterface, EventRoomInterface
    {           
        /**
         * Changel name. For client side this is nsp.
         */
        public static function broadcastOn(): array
        {
            return ['notifications'];
        }
    
        /**
         * Event name
         */
        public static function name(): string
        {
            return 'update_notification_count';
        }
           
        /**
         * Socket.io room
         * @return string
         */
        public function room(): string
        {
            return 'user_id_' . $this->userId;
        }            
            
        /**
         * Emit client event
         * @return array
         */
        public function fire(): array
        {                        
            return [
                'count' => 10,
            ];
        }
    }

Client side

    var socket = io('{your_host_address}:1367/notifications');
    socket.emit('join', {room: 'user_id_10'});
    // Now you will receive data from 'room-1'
    socket.on('update_notification_count', function(data){
        console.log(data)
    });
    // You can leave room
    socket.emit('leave', {room: 'user_id_10'});

Run this on the backend side

$this->broadcast->emit('update_notification_count', ['some key' => 'some value', 'userId' => 10]);
Default events:
  • connection
  • disconnect
  • join
  • leave
    use SfCod\SocketIoBundle\Events\EventSubscriberInterface;
    use SfCod\SocketIoBundle\Events\EventInterface;
    use Psr\Log\LoggerInterface;
    use SfCod\SocketIoBundle\Events\AbstractEvent;
    
    class СonnectionEvent extends AbstractEvent implements EventInterface, EventSubscriberInterface
    {

        private $logger;
    
        public function __construct(LoggerInterface $logger)
        {
            $this->logger = $logger;
        }

        /**
         * Changel name. For client side this is nsp.
         */
        public static function broadcastOn(): array
        {
            return ['notifications'];
        }
    
        /**
         * Event name
         */
        public static function name(): string
        {
            return 'connection'; // or 'disconnect'
        }     
        
        /**
         * Handle client event
         */
        public function handle()
        {
            // Socket.io ID
            // $this->socketId
            $this->logger->info('disconnect', $this->payload);
        }
    }

sfcod/socketio 适用场景与选型建议

sfcod/socketio 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2.69k 次下载、GitHub Stars 达 25, 最近一次更新时间为 2018 年 02 月 20 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 sfcod/socketio 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 sfcod/socketio 我们能提供哪些服务?
定制开发 / 二次开发

基于 sfcod/socketio 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 2.69k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 25
  • 点击次数: 10
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 25
  • Watchers: 3
  • Forks: 8
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2018-02-20