【问题标题】:Socket.io and Phalcon PHPSocket.io 和 Phalcon PHP
【发布时间】:2016-10-12 05:55:09
【问题描述】:

我正在使用Phalcon PHP,我想第一次尝试socket.io。我用socket.io做了教程聊天消息。但是现在我想在我的数据库中选择一些数据来使用查询 Phalcon 计算表“产品”中的行数:

$count_products = Product::count();

例如,在我的 HTML 页面中,我有 5 个产品,当我将一个或多个产品添加到我的产品表中时,我希望自动刷新以在我的 HTML 页面中查看 6 个产品。

你能帮我做吗?

【问题讨论】:

  • 这不是一个答案,但我强烈建议使用专为套接字设计的工具,例如Node.js,它特别适合提供实时连接内容。在您的情况下,Phalcon 是 RESTful api 的最佳选择。
  • 你的意思是我不应该使用 socket.io 但我必须使用 Node.js 来创建我的套接字并使用 Phalcon 服务器端来创建我的 Web 服务?我所有的网络服务都将被 Node js socket 消费?
  • 不。使用 socket.io 后,您可以将它与 node.js 一起用作服务器端,它能够连接到 db 并提供您需要动态提供的数据。 Here 您可以在示例方法中找到进一步的解释。
  • 好的,我明白你的意思了。但是我必须保留 phalcon 服务器端,因为这是一个非常好的 php 框架,他很快,我不能完全删除 phalcon,因为我所有的项目都是用他构建的。我可以在我的视图中实时使用 phalcon 服务器端并使用 socket io 吗?还是两者都用不好?

标签: php mysql socket.io phalcon


【解决方案1】:

一旦你在 ajax 请求上使用套接字,你应该保持你的 Phalcon 保持原样,并尝试使用 node.js+socket.io 实现简单的工具。

最简单的方法是在 Node 中创建一个事件转发器,它会在一侧监听事件,并将它们转发到用户浏览器。更多描述here

在您的情况下,我建议在您的 Phalcon 模型中添加一个 afterSave 监听器,如 documentation 中所述。在afterSave 方法期间,您将能够通过例如。向您的 Node 服务发送一个 UDP 数据包,其中包含 X 表中有新记录的信息。

您的 Node 服务应该将此事件转发给客户端的浏览器,由 javascript 决定当前用户是否正在查看 X 表。如果是,它应该锁定视图以防止任何操作并向 Phalcon 服务发起 ajax 请求,该服务应该向您的数据库询问实际数据并刷新视图中的 HTML 内容。

当然,您可以创建一个 Node 服务,它可以直接在 DB 上侦听更改,并将适当的事件发送给适当的用户,所有内容都准备好完全动态更新。但这是一种先进的方法,可能有点矫枉过正。我想在这里强调一下,只要您的 Phalcon 服务针对速度进行了优化并且发送的数据不是太大,建议的解决方案就可以在几分之一秒内工作,给人一种实时的感觉。

当然,您可以使用 Phalcon 而不是 Node 创建转发服务,但时间长了您会后悔的,因为使用基于事件的工具来维护这种基于事件的脚本更容易。同样对于不时使用 JavaScript 的高级 PHP 程序员来说,快速学习这么一点点 Note.js 以做出如此简单的解决方案甚至都不是挑战。

使用 PHP 通过套接字发送包

$host = array(
    'scheme' => 'udp', // udp makes it lightweight and connectionless
    'host' => '192.168.10.10' // choose an IP where node is running
    'port' => '8888' // choose one > 1023
);
$param = sprintf('%s://%s:%s', $host['scheme'], $host['host'], $host['port']);
$socket = fsockopen($param, $errno, $errstr, $timeout);

我确实在Socket 类中包含了类似的内容。我宁愿使用持久套接字(pfsockopen),因此即使看起来不是这样,一次很少有进程会使用这个套接字。在afterSave 我使用Send 方法,或多或少:

fwrite($socket, json_encode($msg));

基于 websocket 的 Node.js 事件转发脚本

示例配置文件node.json:

{
    "wsServer": {
        "listeners": {
            "udp": {
                "port": 8888
            }
        },
        "server": {
            "port": 8000
        }
    }
}

您的依赖项将是 socket.iodgram。一旦你学会了如何创建 Node 应用程序,你稍后就会明白我的意思。

为了便于理解以下内容:

var config = require('node.json').wsServer;
var app = require('http').createServer().listen(config.server.port);
var io = require('socket.io').listen(app);
var listenerDgram = require('dgram').createSocket('udp4');
listenerDgram.bind(config.listeners.udp.port);

var users = {};

io.sockets.on('connection', function(socket) {
    // if you make user to connect by his individual ID during
    // websocket connection, providen after ?, like ?1234
    var user = parseInt(socket.handshake.query.user);

    // here to save user into var users
    if (!users[user]) {
        users[user] = {
            sockets: [socket]
        };
    } else {
        users[user].sockets.push(socket);
    }

    socket.on('disconnect', function() {
        // removing user from var users
        // warning: socket by socket, and if last
        //   socket is closed, remove whole user section
    });

});

// to emit data to all sockets of choosen users
emit = function(sockets, message, data) {
    for (var x in sockets) {
        if (sockets[x]) {
            sockets[x].emit(message, data);
        }
    }
};

// now UDP listening section
listenerDgram.on('message', function(msg, rinfo) {

    // you can declare checkIncoming if you have standarized
    // frames, or just use msg as it is
    var _dat = checkIncoming(msg.toString().trim(), true);
    var _response = {
        action: _dat.action,
        data: _dat.data
    };

    // you can declare standarizeFrame to define your own protocol,
    // or just use _response.
    var frame = standarizeFrame(_response);

    if (_dat.user) { // emitting to single user declared
        emit(users[_dat.user].sockets, 'notification', frame);
    } else { // emitting to all connected users
        io.emit('notification', frame);
    }
});

因此,您将 JSON 化的字符串发送到 Node 在端口 8888 上运行的服务器,并且用户 Web 界面连接到端口 8000 上的同一主机以接收它们。大量的调试工作摆在您面前。

PS:很抱歉这么武断的回答,但我自己走过它,因为我爱上了 Phalcon 并且不知道 Node.js 是否存在。给自己时间学习 Node 帮助我将基于事件的解决方案减少到绝对最低限度,将它们包含在 100 行而不是数千行中,使它们易于维护,让我的服务器深呼吸 CPU 和比基于 php 的客户端更满意.

【讨论】:

  • 非常感谢您的回答。所以我会尝试用afterSave来实现你的方法。这似乎是最好的方法,它比 SQL 查询上的无限循环要好:)。
  • 但是您能告诉我如何从 afterSave 向节点 js 发送消息吗?
  • 这里有更多信息。希望现在就足够了。
  • 哇,非常感谢,这真的很好,我会试试的。因此,在您的 sn-p 中使用 ratchet 或elephant.io 是没有用的:)
猜你喜欢
  • 1970-01-01
  • 2014-04-30
  • 2016-12-29
  • 2023-04-01
  • 2013-05-15
  • 2014-06-20
  • 1970-01-01
  • 2020-01-03
  • 2021-04-08
相关资源
最近更新 更多