yiicod / yii2-socketio
为Yii2框架提供的简单而强大的socketio
1.2.3
2018-06-15 16:51 UTC
Requires
- predis/predis: ~1.1.0
- symfony/process: ~3.0|~4.0
- yiicod/yii2-base: 1.*
- yiicod/yii2-cron: 1.*
- yiisoft/yii2: 2.*
Requires (Dev)
README
在您的Yii 2项目中使用socket.io的全部功能。
配置
安装node + npm
cd ~ curl -sL https://deb.nodesource.com/setup_6.x -o nodesource_setup.sh sudo bash nodesource_setup.sh cd vendor/yiicod/yii2-socketio/server npm install
控制台配置(简单分支)
'controllerMap' => [ 'socketio' => [ 'class' => \yiicod\socketio\commands\SocketIoCommand::class, 'server' => 'localhost:1367' ], ]
启动socketio服务器
php yii socketio/start
停止socketio服务器
php yii socketio/stop
控制台配置 + PM2(https://pm2.node.org.cn/)。此变体更适用于控制台配置
'controllerMap' => [ 'socketio' => [ 'class' => \yiicod\socketio\commands\WorkerCommand::class, 'server' => 'localhost:1367' ], ]
pm2配置
{ "apps": [ { "name": "socket-io-node-js-server", "script": "yii", "args": [ "socketio/node-js-server" ], "exec_interpreter": "php", "exec_mode": "fork_mode", "max_memory_restart": "1G", "watch": false, "merge_logs": true, "out_file": "runtime/logs/node_js_server_out.log", "error_file": "runtime/logs/node_js_server_err.log" }, { "name": "socket-io-php-server", "script": "yii", "args": [ "socketio/php-server" ], "exec_interpreter": "php", "exec_mode": "fork_mode", "max_memory_restart": "1G", "watch": false, "merge_logs": true, "out_file": "runtime/logs/php_server_out.log", "error_file": "runtime/logs/php_server_err.log" }, ] }
运行PM2守护进程
pm2 start daemons-app.json
PM2将在后台运行以下两个命令:
php yii socketio/node-js-server php yii socketio/php-server
通用配置
'components' =>[ 'broadcastEvents' => [ 'class' => \yiicod\socketio\EventManager::class, 'nsp' => 'some_unique_key', // Namespaces with events folders 'namespaces' => [ 'app\socketio', ] ], 'broadcastDriver' => [ 'class' => \yiicod\socketio\drivers\RedisDriver::class, 'hostname' => 'localhost', 'port' => 6379, ], ]
从服务器创建发布者到客户端
use yiicod\socketio\events\EventInterface; use yiicod\socketio\events\EventPubInterface; class CountEvent implements EventInterface, EventPubInterface { /** * Channel 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 * @param array $data * @return array */ public function fire(array $data): array { return $data; } }
var socket = io('localhost:1367/notifications'); socket.on('update_notification_count', function(data){ console.log(data) });
//Run broadcast to client \yiicod\socketio\Broadcast::emit(CountEvent::name(), ['count' => 10])
从客户端创建接收者到服务器
use yiicod\socketio\events\EventInterface; use yiicod\socketio\events\EventSubInterface; class MarkAsReadEvent implements EventInterface, EventSubInterface { /** * Channel 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'; } /** * Emit client event * @param array $data * @return array */ public function handle(array $data) { // Mark notification as read // And call client update // Broadcast::emit('update_notification_count', ['some_key' => 'some_value']); // Push some log file_put_contents(\Yii::getAlias('@app/../file.txt'), serialize($data)); } }
var socket = io('localhost:1367/notifications'); socket.emit('mark_as_read_notification', {id: 10});
您可以在一个事件中拥有发布者和接收者。如果您需要从客户端检查数据到服务器,您应该使用
- EventPolicyInterface
带有客户端到服务器检查的接收者
use yiicod\socketio\events\EventSubInterface; use yiicod\socketio\events\EventInterface; use yiicod\socketio\events\EventPolicyInterface; class MarkAsReadEvent implements EventInterface, EventSubInterface, EventPolicyInterface { /** * Channel 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 * @param array $data * @return array */ public function handle(array $data) { // Mark notification as read // And call client update Broadcast::emit('update_notification_count', ['some_key' => 'some_value']); } }
Socket.io具有房间功能。如果您需要它,您应该实现
- EventRoomInterface
use yiicod\socketio\events\EventPubInterface; use yiicod\socketio\events\EventInterface; use yiicod\socketio\events\EventRoomInterface; class CountEvent implements EventInterface, EventPubInterface, EventRoomInterface { /** * User id * @var int */ protected $userId; /** * Channel 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 * @param array $data * @return array */ public function fire(array $data): array { $this->userId = $data['userId']; return [ 'count' => 10, ]; } }
var socket = io('localhost: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');
//Run broadcast to user id = 10 \yiicod\socketio\Broadcast::emit(CountEvent::name(), ['count' => 10, 'userId' => 10])