yii-node-socket

Connect php, javascript, nodejs in one Yii application.
12 followers

If you need create more live application this extension helps you with it.

Based on nodejs socket.io library.

Features:

  • emit events to all connected clients
  • create rooms and emit events into some room
  • set up data in nodejs memory from php and get in from javascript
  • invoke any function or method of object in javascript (in window scope) from php
  • browser support

Github page

Requirements

OS: linux/unix/windows
git installed

Installation

Install nodejs, if not installed see nodejs official site
Install extension

  • Using git clone
$> git clone git@github.com:oncesk/yii-node-socket.git

Now go to the folder where you install extension application.ext.yii-node-socket and execute

$> git submodule init
$> git submodule update

Yii configuration

  • Configure console command in (main/console.php). You can use config below:
'commandMap' => array(
    'node-socket' => 'application.extensions.yii-node-socket.lib.php.NodeSocketCommand'
)
  • Register Yii component, need to add into main.php and console.php:
'nodeSocket' => array(
    'class' => 'application.extensions.yii-node-socket.lib.php.NodeSocket',
    'host' => 'localhost',  // default is 127.0.0.1, can be ip or domain name, without http
    'port' => 3001      // default is 3001, should be integer
)

Install nodejs components in application.ext.yii-node-socket.lib.js.server:

$> npm install

Congratulation, installation completed!

Notice: if the name of the component will not be nodeSocket, your need to use special key in console command --componentName=component_name

Console command actions

$> ./yiic node-socket # show help
$> ./yiic node-socket start # start server
$> ./yiic node-socket stop # stop server
$> ./yiic node-socket restart # restart server
$> ./yiic node-socket getPid # show pid of nodejs process

Javascript

before work in javascript you need start server (./yiic node-socket start) and register clients scripts in PHP (see below, into PHP section)

// create object and connect to web socket server
var socket = new YiiNodeSocket();

// enable debug mode
socket.debug(true);

// add event listener
socket.on('updateBoard', function (data) {
    // do any action
});

socket.room('testRoom').join(function (success, numberOfRoomSubscribers) {
    // success - boolean, numberOfRoomSubscribers - number of room members
    // if error occurred then success = false, and numberOfRoomSubscribers - contains error message
    if (success) {
        console.log(numberOfRoomSubscribers + ' clients in room: ' + roomId);
        // do something

        // bind events
        this.on('join', function (newMembersCount) {
            // fire on client join
        });

        this.on('data', function (data) {
            // fire when server send frame into this room with 'data' event
        });
    } else {
        // numberOfRoomSubscribers - error message
        alert(numberOfRoomSubscribers);
    }
});

PHP

Registering client scripts

Yii::app()->nodeSocket->registerClientScripts();

Frames

Frame - data package for nodejs server wrapped into Class. Per one request to nodejs server you can send only 1 frame. For send several frames at a time use Multiple frame.

Frames:

  • Event - send event to javascript
  • Invoke - invoke javascript function or method of object in window scope
  • PublicData - set up shared data into nodejs memory, any client can get it
  • Multiple - needed for sending more several frames per a time

Event frame

// create event frame
$frame = Yii::app()->nodeSocket->createEventFrame();
 
// set event name
$frame->setEventName('updateBoard');
 
// set data using ArrayAccess interface
$frame['boardId'] = 25;
$frame['boardData'] = $html;
 
// or you can use setData(array $data) method
// setData overwrite data setted before
 
$frame->send();

Set up shared data

Notice: You can set expiration using setLifeTime(integer $lifetime) method of class PublicData

// create frame
$frame = Yii::app()->nodeSocket->createPublicDataFrame();
 
// set key in storage
$frame->setKey('error.strings');
 
// set data
$frame->setData($errorStrings);
 
// you can set data via ArrayAccess interface
// $frame['empty_name'] = 'Please enter name';
 
// set data lifetime
$frame->setLifeTime(3600*2);    // after two hours data will be deleted from storage
 
// send
$frame->send();

Send event into room

// create frame
$frame = Yii::app()->nodeSocket->createEventFrame();
 
// set event name
$frame->setEventName('updateBoard');
 
// set room name
$frame->setRoom('testRoom');
 
// set data
$frame['key'] = $value;
 
// send
$frame->send();

Invoke javascript function

$invokeFrame = Yii::app()->nodeSocket->createInvokeFrame();
$invokeFrame->invokeFunction('alert', array('Hello world'));
$invokeFrame->send();   // alert will be showed on all clients

DOM manipulations with jquery

Task: you need update price on client side after price update in each product

...
 
$product = Product::model()->findByPk($productId);
if ($product) {
    $product->price = $newPrice;
    if ($product->save()) {
        $jFrame = Yii::app()->nodeSocket->createJQueryFrame();
        $jFrame
            ->createQuery('#product' . $product->id)
            ->find('span.price')
            ->text($product->price);
        $jFrame->send();
        // and all connected clients will can see updated price
    }
}
 
...

Send more than one frame per a time

Example 1:

$multipleFrame = Yii::app()->nodeSocket->createMultipleFrame();
 
$eventFrame = Yii::app()->nodeSocket->createEventFrame();
 
$eventFrame->setEventName('updateBoard');
$eventFrame['boardId'] = 25;
$eventFrame['boardData'] = $html;
 
$dataEvent = Yii::app()->nodeSocket->createPublicDataFrame();
 
$dataEvent->setKey('error.strings');
$dataEvent['key'] = $value;
 
$multipleFrame->addFrame($eventFrame);
$multipleFrame->addFrame($dataEvent);
$multipleFrame->send();

Example 2:

$multipleFrame = Yii::app()->nodeSocket->createMultipleFrame();
 
$eventFrame = $multipleFrame->createEventFrame();
 
$eventFrame->setEventName('updateBoard');
$eventFrame['boardId'] = 25;
$eventFrame['boardData'] = $html;
 
$dataEvent = $multipleFrame->createPublicDataFrame();
 
$dataEvent->setKey('error.strings');
$dataEvent['key'] = $value;
 
$multipleFrame->send();

See github for more documentation above!

Resources

Total 11 comments

#16591 report it
once at 2014/03/09 03:22am
there is no way

Hello, i guess server side it's PHP? in current version no ability to get number of connected clients, or clients in concrete room, but

On this week i try implement this.

#16589 report it
inProcess at 2014/03/08 09:32pm
How many clients are on

Hi once! On the server side, is there a way to find out if there is more than one client in any one room?

#16537 report it
once at 2014/03/03 04:29pm
yes, it should works for different views

Yes, it should works for different views but for same rooms, in any view you can join into some room and send event into this room, in any view it should works!

#16536 report it
inProcess at 2014/03/03 03:06pm
Yes it works within same view file!

My prior inquiry was for a common room loaded within two different views. So I retested this for a common room loaded for the same view. It does work for the same view! So my question, is should it work for same room-different views also?

#16532 report it
once at 2014/03/03 04:31am
hm, all clients in the room can send and catch events from any client in the room

if your clients connected in some room, clients can:

  • send events in this room for all room members
  • catch events in current room

if this functionality did not works try create issue on github

And several days ago i update extension, see more on github, maybe it helps Today i try test it again and give you more explanations

Thank you

#16528 report it
inProcess at 2014/03/03 02:02am
A group within a room

I have a room set up and I have four clients that have joined the room. I understand that only one client can send a message event to all the others plus itself, but the others can not send message events for the room to see. My question: Is there a way for everyone in the room to send message events and everyone in the room see the messages (sort of like a group chat within that room only)?

#16445 report it
once at 2014/02/24 01:24am
seems like only one client connected

Hi, in your logs, your emit frame and only after that your page is loaded and client javascript can catch events, try open more then one page in your browser

All frames take effect to connected sockets

I thin, this helps you

Thank you.

#16444 report it
inProcess at 2014/02/23 11:28pm
On every $frame->(send)

On every $frame->(send) when I create an event for the client side to recognize, I am getting the below in my log file socket-transport.server.log

info: socket.io started
Listening localhost:3001
Set origin: localhost:*
debug: client authorized info: handshake authorized uEY2xdiEL0O9GHY8HZH-
debug: setting request GET /socket.io/1/websocket/uEY2xdiEL0O9GHY8HZH-
debug: set heartbeat interval for client uEY2xdiEL0O9GHY8HZH-
debug: client authorized for
debug: websocket writing 1::
debug: client authorized for /server
debug: websocket writing 1::/server
info: transport end (undefined)
debug: set close timeout for client uEY2xdiEL0O9GHY8HZH-
debug: cleared close timeout for client uEY2xdiEL0O9GHY8HZH-
debug: cleared heartbeat interval for client uEY2xdiEL0O9GHY8HZH-
debug: discarding transport
debug: served static content /socket.io.js

I am using the exact code examples on branch 0.1

Is there something simple I am missing? Or can you lead me in the direction to rectify this? I've been trying to figure this out for a few days, and I am just not receiving anything on the client side.

Thanks so much for any help or comments.

#16375 report it
inProcess at 2014/02/16 01:23pm
Okay Thanks!

I definitely understand these busy days. Well I appreciate your hard work, and I do thank you for what you have done!

thanks!

#16372 report it
once at 2014/02/16 08:53am
github

see github page, for more examples need more time but i do not have it) maybe later

https://github.com/oncesk/yii-node-socket/tree/0.1

Thank you

#16370 report it
inProcess at 2014/02/15 10:52pm
Superb Work!

I am so glad to start using this in my project. It was such a great idea to integrate Node.js and Socket.io with Yii. Kudos to YOU! Would you provide a demo, downloadable examples, or instructional videos to help with using this? Also this would be great to integrate with Yiinitializr advanced structure!

Leave a comment

Please to leave your comment.

Create extension
Downloads
No downloadable files yet