yiicod / yii2-socketio
The simple and powerful socketio for the Yii2 framework
Installs: 17 899
Dependents: 0
Suggesters: 0
Security: 0
Stars: 46
Watchers: 7
Forks: 30
Open Issues: 5
Type:yii2-extension
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
Use all power of socket.io in your Yii 2 project.
Config
Install node + additional 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
Console config (simple fork)
'controllerMap' => [ 'socketio' => [ 'class' => \yiicod\socketio\commands\SocketIoCommand::class, 'server' => 'localhost:1367' ], ]
Start sockeio server
php yii socketio/start
Stop sockeio server
php yii socketio/stop
Console config + PM2(http://pm2.keymetrics.io/). This variant more preferable for console configuration
'controllerMap' => [ 'socketio' => [ 'class' => \yiicod\socketio\commands\WorkerCommand::class, 'server' => 'localhost:1367' ], ]
pm2 config:
{ "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" }, ] }
Run PM2 daemons
pm2 start daemons-app.json
PM2 will be run these two commands in background::
php yii socketio/node-js-server php yii socketio/php-server
Common config
'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, ], ]
Create publisher from server to client
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])
Create receiver from client to server
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});
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 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']); } }
Soket.io has room functionl. If you need it, you should implement:
- 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])