车轮升级PHP7踩过的一些坑

来自PHP百科全书
跳转至: 导航搜索

社区php7升级记录

社区服务器已经全部完成升级,这里记录一下社区升级php7所遇到的问题,可以分为四个类型

  1. 扩展支持的变化,导致需要修改配置甚至调整替换操作的类库
  2. php7语法检查比之前变得严格,部分之前能正常执行的写法,现在会有warning提示,甚至fatal error
  3. 部分函数的被弃用
  4. 我们的一处代码意外触发了php7本身的一处bug,已经在php官网提交并得到反馈

第一种情况:扩展的变化

1. 不支持mysql扩展,改用mysqli

  这个比较简单修改配置信息就好

2. 不支持memcache扩展,改用memcached

这里有比较大的坑,我们测试过memcache与memcached的哈希规则是不一致的,甚至存储写入时两个扩展设置的数据类型flag都是不一致的,导致memcache扩展写入
的数组,在memcached扩展读出来是原始的序列化字符串。
所以两者在集群甚至单点模式下都是无法兼容的.
之后我们尝试过在php5.6上也启用memcached,不过发现两个不同版本的memcached的哈希规则竟然都不一样。
最后我们的解决方案是php7使用新的集群,与旧有的隔离,同个判断php版本已经扩展是否存在来使用哪种扩展与配置

3. 不支持mongo扩展,改用mongodb扩展

 扩展变化导致原先的mongodb操作的类库不可用,我们根据php版本来判断具体使用哪一种

参考:https://segmentfault.com/a/1190000007158136

也可以是用开源的mongo适配器实现兼容。

 composer require alcaeus/mongo-php-adapter

第二种情况:语法检查变化

php7某种情况自动类型转换会出问题

$pids = '';
$pids[] = array();

使用[]操作,出现Fatal error

PHP Fatal error:  Uncaught Error: [] operator not supported for strings

函数定义这里php7的参数校验和5.6有差异

function a($param1, $param2, $param1 = array()){}

这样的方式php5.6不会报错,7会报fatal error.

PHP Fatal error:  Redefinition of parameter $param1 in

以数组的形式给字符串赋值,会报错

PHP Warning:  Cannot assign an empty string to a string offset

第三种情况:部分函数被弃用或调用方式调整

正则匹配preg_replace 函数的 e 修饰符功能在php7被弃用(其他修饰符模式,正常使用),需要回调执行,则用preg_replace_callback来替代

  1. 例子:将__TABLE_NAME__这样的字符串替换成正规的表名,并且带上前缀
$joinStr = preg_replace("/__([A-Z_-]+)__/e",$prex.".strtolower('$1')",$joinStr);
//替换为
preg_replace_callback("/__([A-Z_-]+)__/",function($r) use (&$joinStr){
    $joinStr = $prex.strtolower($r[1]);
},$joinStr);

第四种情况:触发php7 bug

在将一台cgi服务器升级到php后,时不时会收到超时报警,定位后发现是某种特殊情况下触发了php7的bug 我们已经把bug提交到官网 https://bugs.php.net/bug.php?id=74431

注:PHP官方在第二天就修复了此BUG,最新的 7.1.5 就没问题了