返回介绍

1.16.37 PHP的几种回调写法

发布于 2020-05-17 11:52:44 字数 8660 浏览 1064 评论 0 收藏 0

PHP里通过匿名函数写回调是最方便的,但是除了匿名函数方式的回调,PHP还有其它的回调写法。以下是PHP几种回调写法的示例。

1、匿名函数回调

<?php
use WorkermanWorker;
require_once __DIR__ . '/Workerman/Autoloader.php';
$http_worker = new Worker("http://0.0.0.0:2345");

// 匿名函数回调
$http_worker->onMessage = function($connection, $data)
{
    // 向浏览器发送hello world
    $connection->send('hello world');
};

Worker::runAll();

2、普通函数回调

<?php
use WorkermanWorker;
require_once __DIR__ . '/Workerman/Autoloader.php';
$http_worker = new Worker("http://0.0.0.0:2345");

// 匿名函数回调
$http_worker->onMessage = 'on_message';

// 普通函数
function on_mesage($connection, $data)
{
    // 向浏览器发送hello world
    $connection->send('hello world');
}

Worker::runAll();

3、类方法作为回调

MyClass.php

class MyClass{
    public function __construct(){}
    public function onWorkerStart($worker){}
    public function onConnect($connection){}
    public function onMessage($connection, $message) {}
    public function onClose($connection){}
    public function onWorkerStop($connection){}
}

启动脚本 start.php

<?php
use WorkermanWorker;
require_once __DIR__ . '/Workerman/Autoloader.php';

// 载入MyClass
require_once __DIR__.'/MyClass.php';

$worker = new Worker("websocket://0.0.0.0:2346");

// 创建一个对象
$my_object = new MyClass();

// 调用类的方法
$worker->onWorkerStart = array($my_object, 'onWorkerStart');
$worker->onConnect     = array($my_object, 'onConnect');
$worker->onMessage     = array($my_object, 'onMessage');
$worker->onClose       = array($my_object, 'onClose');
$worker->onWorkerStop  = array($my_object, 'onWorkerStop');

Worker::runAll();

注意: 以上的代码结构不允许在构造函数里初始化资源(MySQL连接、Redis连接、Memcache连接等),因为$my_object = new MyClass();运行在主进程。以MySQL为例,在主进程初始化的MySQL连接等资源会被子进程继承,每个子进程都可以操作这个数据库连接,但是这些连接在MySQL服务端对应的是同一个连接,会发生不可预期的错误,例如mysql gone away 错误。

以上代码结构如果需要在类的构造函数里初始化资源,可以采用以下写法。 MyClass.php

class MyClass{
    protected $db = null;
    public function __construct(){
        // 假设数据库连接类是MyDbClass
        $db = new MyDbClass();
    }
    public function onWorkerStart($worker){}
    public function onConnect($connection){}
    public function onMessage($connection, $message) {}
    public function onClose($connection){}
    public function onWorkerStop($connection){}
}

启动脚本 start.php

<?php
use WorkermanWorker;
require_once __DIR__ . '/Workerman/Autoloader.php';

$worker = new Worker("websocket://0.0.0.0:2346");

// 在onWorkerStart里初始化类
$worker->onWorkerStart = function($worker) {
    // 载入MyClass
    require_once __DIR__.'/MyClass.php';

    // 创建一个对象
    $my_object = new MyClass();

    // 调用类的方法
    $worker->onConnect    = array($my_object, 'onConnect');
    $worker->onMessage    = array($my_object, 'onMessage');
    $worker->onClose      = array($my_object, 'onClose');
    $worker->onWorkerStop = array($my_object, 'onWorkerStop');
};

Worker::runAll();

上面代码结构中onWorkerStart运行时已经是属于子进程,等于每个子进程各自建立自己的MySQL连接,所以不会有共享连接的问题。 这样还有一个好处就是支持业务代码reload。由于MyClass.php是在子进程载入的,根据reload规则业务更改MyClass.php后直接reload即可生效。

4、类的静态方法作为回调

静态类MyClass.php

class MyClass{
    public static function onWorkerStart($worker){}
    public static function onConnect($connection){}
    public static function onMessage($connection, $message) {}
    public static function onClose($connection){}
    public static function onWorkerStop($connection){}
}

启动脚本 start.php

<?php
use WorkermanWorker;
require_once __DIR__ . '/Workerman/Autoloader.php';

// 载入MyClass
require_once __DIR__.'/MyClass.php';

$worker = new Worker("websocket://0.0.0.0:2346");

// 调用类的静态方法。
$worker->onWorkerStart = array('MyClass', 'onWorkerStart');
$worker->onConnect     = array('MyClass', 'onConnect');
$worker->onMessage     = array('MyClass', 'onMessage');
$worker->onClose       = array('MyClass', 'onClose');
$worker->onWorkerStop  = array('MyClass', 'onWorkerStop');

// 如果类带命名空间,则是类似这样的写法
// $worker->onWorkerStart = array('yournamesapceMyClass', 'onWorkerStart');
// $worker->onConnect     = array('yournamesapceMyClass', 'onConnect');
// $worker->onMessage     = array('yournamesapceMyClass', 'onMessage');
// $worker->onClose       = array('yournamesapceMyClass', 'onClose');
// $worker->onWorkerStop  = array('yournamesapceMyClass', 'onWorkerStop');

Worker::runAll();

注意:根据PHP的运行机制,如果没用调用new 则不会调用构造函数,另外静态类的方法里面不允许使用$this

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文