Skip to content

与 ThinkPHP 等框架结合

使用 GatewayWorker 时开发者最关心的是如何与现有 mvc 框架 (ThinkPHP Yii laravel 等) 整合,以下是官方推荐的整合方式。见示意图:

总体原则:

现有 mvc 框架项目与 GatewayWorker 独立部署互不干扰

所有的业务逻辑都由网站页面 post/get 到 mvc 框架中完成

GatewayWorker 不接受客户端发来的数据,即 GatewayWorker 不处理任何业务逻辑,GatewayWorker 仅仅当做一个单向的推送通道

仅当 mvc 框架需要向浏览器主动推送数据时才在 mvc 框架中调用 Gateway 的 API GatewayClient 完成推送。

GatewayClient 安装

参考地址 https://github.com/walkor/GatewayClient

具体实现步骤

1、网站页面建立与 GatewayWorker 的 websocket 连接

2、GatewayWorker 发现有页面发起连接时,将对应连接的 client_id 发给网站页面

3、网站页面收到 client_id 后触发一个 ajax 请求 (假设是 bind.php ) 将 client_id 发到 mvc 后端

4、mvc 后端 bind.php 收到 client_id 后利用 GatewayClient 调用 Gateway::bindUid($client_id, $uid) 将 client_id 与当前 uid (用户 id 或者客户端唯一标识) 绑定。如果有群组、群发功能,也可以利用 Gateway::joinGroup($client_id, $group_id) 将 client_id 加入到对应分组

5、页面发起的所有请求都直接 post/get 到 mvc 框架统一处理,包括发送消息

6、mvc 框架处理业务过程中需要向某个 uid 或者某个群组发送数据时,直接调用 GatewayClient 的接口 Gateway::sendToUid Gateway::sendToGroup 等发送即可

示例代码

GatewayWorker 中 Events.php 代码(只有个 onConnect 回调设置)

php
<?php
use \GatewayWorker\Lib\Gateway;
class Events
{
    // 当有客户端连接时,将client_id返回,让mvc框架判断当前uid并执行绑定
    public static function onConnect($client_id)
    {
        Gateway::sendToClient($client_id, json_encode(array(
            'type'      => 'init',
            'client_id' => $client_id
        )));
    }

    // GatewayWorker建议不做任何业务逻辑,onMessage留空即可
    public static function onMessage($client_id, $message)
    {

    }
}

网站页面 js 片段

javascript
/**
 * 与GatewayWorker建立websocket连接,域名和端口改为你实际的域名端口,
 * 其中端口为Gateway端口,即start_gateway.php指定的端口。
 * start_gateway.php 中需要指定websocket协议,像这样
 * $gateway = new Gateway(websocket://0.0.0.0:7272);
 */
ws = new WebSocket("ws://your_domain.com:7272");
// 服务端主动推送消息时会触发这里的onmessage
ws.onmessage = function(e){
    // json数据转换成js对象
    var data = eval("("+e.data+")");
    var type = data.type || '';
    switch(type){
        // Events.php中返回的init类型的消息,将client_id发给后台进行uid绑定
        case 'init':
            // 利用jquery发起ajax请求,将client_id发给后端进行uid绑定
            $.post('./bind.php', {client_id: data.client_id}, function(data){}, 'json');
            break;
        // 当mvc框架调用GatewayClient发消息时直接alert出来
        default :
            alert(e.data);
    }
};

mvc 后端 uid 绑定代码片段 bind.php (利用 GatewayClient 绑定)

php
<?php
//加载GatewayClient。关于GatewayClient参见本页面底部介绍
require_once '/your/path/GatewayClient/Gateway.php';
// GatewayClient 3.0.0版本开始要使用命名空间
use GatewayClient\Gateway;
// 设置GatewayWorker服务的Register服务ip和端口,请根据实际情况改成实际值(ip不能是0.0.0.0)
Gateway::$registerAddress = '127.0.0.1:1236';

// 假设用户已经登录,用户uid和群组id在session中
$uid      = $_SESSION['uid'];
$group_id = $_SESSION['group'];
// client_id与uid绑定
Gateway::bindUid($client_id, $uid);
// 加入某个群组(可调用多次加入多个群组)
Gateway::joinGroup($client_id, $group_id);

mvc 后端发消息代码片段 send_message.php (利用 GatewayClient 发送)

php
<?php
//加载GatewayClient。关于GatewayClient参见本页面底部介绍
require_once '/your/path/GatewayClient/Gateway.php';
// GatewayClient 3.0.0版本开始要使用命名空间
use GatewayClient\Gateway;
// 设置GatewayWorker服务的Register服务ip和端口,请根据实际情况改成实际值(ip不能是0.0.0.0)
Gateway::$registerAddress = '127.0.0.1:1236';

// 向任意uid的网站页面发送数据
Gateway::sendToUid($uid, $message);
// 向任意群组的网站页面发送数据
Gateway::sendToGroup($group, $message);

注意

以上仅是 mvc 框架与 GatewayWorker 官方推荐的结合方式,并不是强制使用此方式,开发者可以自由变化选择结合方式以适应自己的业务需求。 当然也可以采用客户端与 GatewayWorker 直接双向通讯的方式完成业务通讯。

关于 GatewayClient

源码:

https://github.com/walkor/GatewayClient

注意:

如果 GatewayClient 和 GatewayWorker 不是在同一台服务器上,则需要先将 start_gateway.php 中的 lanIp 改成当前服务器的内网 ip(如果不在一个内网可改成公网 ip)。

如果 GatewayClient 和 GatewayWorker 在同一台服务器上运行,则不用做任何更改,直接按照示例使用 GatewayClient 即可。

通过 GatewayClient 发送的数据不会经过 Event.php,而是直接经由 Gateway 进程转发给客户端。

GatewayClient 无法接收客户端发来的数据。

客户端使用示例

php
require_once '/your/path/GatewayClient/Gateway.php';

/**
 * gatewayClient 3.0.0及以上版本加了命名空间
 * 而3.0.0以下版本不需要use GatewayClient\Gateway;
 **/
use GatewayClient\Gateway;

/**
 *====这个步骤是必须的====
 *这里填写Register服务的ip和Register端口,注意端口不是gateway端口
 *ip不能是0.0.0.0,端口在start_register.php中可以找到
 *这里假设GatewayClient和Register服务都在一台服务器上,ip填写127.0.0.1。
 *如果不在一台服务器则填写真实的Register服务的内网ip(或者外网ip)
 **/
Gateway::$registerAddress = '127.0.0.1:1236';


// 以下是调用示例,接口与GatewayWorker环境的接口一致
// 接口具体使用方法见《Lib\Gateway类提供的接口》一章
// 注意除了不支持sendToCurrentClient和closeCurrentClient方法
// 其它方法都支持
Gateway::sendToAll($data);
Gateway::sendToClient($client_id, $data);
Gateway::closeClient($client_id);
Gateway::isOnline($client_id);
Gateway::bindUid($client_id, $uid);
Gateway::isUidOnline($uid);
Gateway::getClientIdByUid($uid);
Gateway::unbindUid($client_id, $uid);
Gateway::sendToUid($uid, $data);
Gateway::joinGroup($client_id, $group);
Gateway::sendToGroup($group, $data);
Gateway::leaveGroup($client_id, $group);
Gateway::getClientCountByGroup($group);
Gateway::getClientSessionsByGroup($group);
Gateway::getAllClientCount();
Gateway::getAllClientSessions();
Gateway::setSession($client_id, $session);
Gateway::updateSession($client_id, $session);
Gateway::getSession($client_id);
...

基于 MIT 许可发布