Deliverer 1.0.8 支持 PHP5 了-阿里云开发者社区

开发者社区> 游客gye3zld3twwee> 正文

Deliverer 1.0.8 支持 PHP5 了

简介: 经历了两周的迭代,Deliverer 目前更新到了 1.0.8 ,因为是为了解决祖传代码的问题,也听到群友的一些声音,还是很有必要支持下 PHP5 的,所以这段时间一直在着力解决这个版本兼容问题,没想到问题比较我预计的要难很多。
+关注继续查看

经历了两周的迭代,Deliverer 目前更新到了 1.0.8 https://github.com/zhoumengkang/deliverer

因为是为了解决祖传代码的问题,也听到群友的一些声音,还是很有必要支持下 PHP5 的,所以这段时间一直在着力解决这个版本兼容问题,没想到问题比较我预计的要难很多。

记录下开发中遇到的问题(主要是体力活)也想分享之后,有兴趣的朋友可以fork一份之后,对代码不那么陌生,更期待各位个 PR

在 PHP7 中,函数或者方法在执行的时候都在zend_execute_data结构体中的execute_data->call->fbc中,而 PHP5 中对应的字段拿到的却是调用该函数的函数,二者差距比较大。

后来发现 PHP5 zend_execute_dataopline中查到了当前执行的函数信息,但在 PHP5.4 前后逻辑还有差异,需要区别对待(还好编译器提示报错的字段)

#if PHP_VERSION_ID < 50400
#define OP1_FUNCTION_PTR(n) (&(n)->op1.u.constant)
#else
#define OP1_FUNCTION_PTR(n) ((n)->op1.zv)
#endif

初次调用解决了,发现内嵌的调用,又不在opline里面了,而且版本不一样,取得地方也不一样,并且和上面的 opline 的判断版本号还不一样,这就只能靠体力来测了。

#if PHP_VERSION_ID < 50500
    if (execute_data->fbc != NULL)
    {
        fbc = execute_data->fbc;
    }
#else
    if (execute_data->call != NULL && execute_data->call->fbc != NULL)
    {
        fbc = execute_data->call->fbc;
    }
#endif

最终获取函数信息就是多层判断

    zend_function *fbc;

#if PHP_VERSION_ID < 70000
#if PHP_VERSION_ID < 50500
    if (execute_data->fbc != NULL)
    {
        fbc = execute_data->fbc;
    }
#else
    if (execute_data->call != NULL && execute_data->call->fbc != NULL)
    {
        fbc = execute_data->call->fbc;
    }
#endif
    if (fbc == NULL)
    {
        fbc = get_function_from_opline(execute_data->opline);
    }
#else
    if (execute_data->call != NULL && execute_data->call->func != NULL)
    {
        fbc = execute_data->call->fbc;
    }
#endif

在从 opline 里查询到的只是函数的名字,需要再去全局函数表里找到对应的函数指针

static zend_function *get_function_from_opline(zend_op *opline)
{
    zend_function *fbc;

    zval *function_name = OP1_FUNCTION_PTR(opline);

    if (Z_STRVAL_P(function_name) == NULL)
    {
        return NULL;
    }

    if (zend_hash_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name) + 1, (void **)&fbc) ==
        FAILURE)
    {
        return NULL;
    }

    return fbc;
}

整体来说 PHP5 的处理要比 PHP7 复杂很多,这也说明 PHP7 做的更好了,点赞。

这些就是这几天的开发工作,可能还有很多实际的线上环境没有遇到过,如果你有兴趣,可以使用这个工具来解决问题,也可以一起来完善这个小工具。

下周或者下下周我将加上 watch 功能,支持函数和方法的参数打印。主要是类比 Java 的 Arthas ,因为在其中 trace 和 watch 功能是我最常用的,虽然 PHP 可以线上直接修改加日志,但是这样毕竟不规范,走发布流程又太慢,我想这个 watch 功能还是很有必要的,大概是

$ ./bin/deliverer -w foo -n 3

表示监控foo函数3次调用后退出,并且打印出deliverer-request-id和其入参,可以再根据deliverer-request-id查看完整的调用栈。

如果觉得有这兴趣,就请给个星星吧,https://github.com/zhoumengkang/deliverer

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
多线程从入门到入坟(面试吹牛逼专用)
提高程序执行效率,比如多线程读取、写入文档等等(摊牌了,我生产中没用过,但这不妨碍我吹牛逼);
4 0
重装服务器,解决怪问题
这一段时间,终于有时间整理服务器了。没办法啊,公司就吾一个搞技术的,服务器不熟悉也得搞啊。
4 0
分布式锁实现思路(面试官直呼内行)
目前java中的synchronized或者juc包中的锁都是针对单个jvm的,分布式环境下就无能为力,只能用分布式锁;
8 0
springboot用实体接收axios get请求参数(亲测有效)
记住,一定要把你的参数包裹过在params里面,比如你的参数变量是params,那你要这样写{params:params},反正我是这样写才成功的
3 0
jquery.tagsinput.js,不错的标签输入框
jquery.tagsinput.js,不错的标签输入框
6 0
WEB前端、后端的说明
这个问题,吾其实认为很简单: 用户看到的部分,就是前端。主要指页面内容。 用户看不到的部分,就是后端。比如数据库、业务逻辑等。 这个说法是不是对的呢?吾上网搜索了一些说法,供大家参考:
4 0
一个简单的小技巧,监控网页所有动态标签创建的调用处
一个简单的小技巧,监控网页所有动态标签创建的调用处
4 0
org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible 已解决
今天修改mybatis的xml文件遇到个这么个问题,找了半天找不到原因,各种回滚,最后发现是注释的原因;
1 0
Java大文件排序(有手就能学会)
注意,这里是为了演示方便,便于小白理解过程,每次直接从文件中读取一个,实际操作中我们不可能每次都只读取一个,IO操作是很耗时的,也不用每次只对比5个
6 0
全网首发:OPPO推送:服务器端的参考代码,JAVA版
近来调试OPPO推送,服务器没有参考代码,简直让人崩溃。于是反复测试,排列组合,找到了正确的办法。也许有朋友也会遇到类似问题,所以在这里把代码共享出来。节省时间不说,最主要心情好一些。
4 0
1
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载