# PHP的几种回调写法
# PHP几种回调写法
PHP里通过匿名函数写回调是最方便的,但是除了匿名函数方式的回调,PHP还有其它的回调写法。以下是PHP几种回调写法的示例。
## 1、匿名函数回调
```php
<?php
use Workerman\Worker;
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
<?php
use Workerman\Worker;
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
```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
<?php
use Workerman\Worker;
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
```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
<?php
use Workerman\Worker;
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
```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
<?php
use Workerman\Worker;
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('your\namesapce\MyClass', 'onWorkerStart');
// $worker->onConnect = array('your\namesapce\MyClass', 'onConnect');
// $worker->onMessage = array('your\namesapce\MyClass', 'onMessage');
// $worker->onClose = array('your\namesapce\MyClass', 'onClose');
// $worker->onWorkerStop = array('your\namesapce\MyClass', 'onWorkerStop');
Worker::runAll();
```
注意:根据PHP的运行机制,如果没用调用new 则不会调用构造函数,另外静态类的方法里面不允许使用```$this```。
- 序言
- 原理
- 开发必读
- 入门指引
- 特性
- 简单的开发示例
- 安装
- 环境要求
- 下载安装
- 启动停止
- 开发流程
- 开发前必读
- 目录结构
- 开发规范
- 基本流程
- 通讯协议
- 通讯协议作用
- 定制通讯协议
- 一些例子
- Worker类
- 构造函数
- 属性
- id
- count
- name
- protocol
- transport
- reusePort
- connections
- stdoutFile
- pidFile
- logFile
- user
- reloadable
- daemonize
- globalEvent
- 回调属性
- onWorkerStart
- onWorkerReload
- onConnect
- onMessage
- onClose
- onBufferFull
- onBufferDrain
- onError
- 接口
- runAll
- stopAll
- listen
- TcpConnection类
- 属性
- id
- protocol
- worker
- maxSendBufferSize
- defaultMaxSendBufferSize
- maxPackageSize
- 回调属性
- onMessage
- onClose
- onBufferFull
- onBufferDrain
- onError
- 接口
- send
- getRemoteIp
- getRemotePort
- close
- destroy
- pauseRecv
- resumeRecv
- pipe
- AsyncTcpConnection类
- 构造函数
- connect
- reconnect
- transport
- Timer定时器类
- add
- del
- 定时器注意事项
- WebServer
- 调试
- 基本调试
- 查看运行状态
- 网络抓包
- 跟踪系统调用
- 常用组件
- GlobalData数据共享组件
- GlobalDataServer
- GlobalDataClient
- Channel分布式通讯组件
- ChannelServer
- channelClient
- 例子-集群推送
- 例子-分组发送
- FileMonitor文件监控组件
- MySQL组件
- workerman/mysql
- swoole/mysql(异步)
- redis组件
- swoole/redis
- 异步http组件
- swoole/http-client
- 异步消息队列组件
- react/zmq
- react/stomp
- 异步dns组件
- swoole/dns
- 常见问题
- 心跳
- 客户端链接失败原因
- 是否支持多线程
- 与其它框架整合
- 运行多个workerman
- 支持哪些协议
- 如何设置进程数
- 查看客户端连接数
- 对象和资源的持久化
- 例子无法工作
- 启动失败
- 停止失败
- 支持多少并发
- 更改代码不生效
- 向指定客户端发送数据
- 如何主动推送消息
- 在其它项目中推送
- 如何实现异步任务
- status里send_fail的原因
- Windows下开发Linux下部署
- 是否支持socket.io
- 终端关闭导致workerman关闭
- 与nginx apache的关系
- 禁用函数检查
- 平滑重启原理
- 为Flash开843端口
- 如何广播数据
- 如何建立udp服务
- 监听ipv6
- 关闭未认证的链接
- 传输加密-ssl/tsl
- 创建wss服务
- 创建https服务
- workerman作为客户端
- 作为ws/wss客户端
- PHP的几种回调写法
- 附录
- Linux内核调优
- 压力测试
- 安装扩展
- websocket协议
- ws协议
- text协议
- frame协议
- 不支持的函数/特性
- 版权信息