最近工作中将php5.2升级到php5.6,在升级的过程中,需要对php各个版本之间的不兼容的问题进行讨论和测试论证。依据php版本不兼容 分支说明 , 分别在多个版本之间进行了测试,分享如下:
1.在 PHP 5.3.x 的所有绑定扩展中应用了新的内部参数解析API, 当给函数传递了不兼容的参数时将返回 NULL. 但有一些例外,比如函数 get_class() 在出现错误时将会返回 FALSE.
解读:这里其实是,php5.3对函数的参数类型相比于php5.2有更强的校验了。比如:参数的类型定义是 int,你传 string,php5.2不报错,php5.3就会报错了。例子如下:
string str_pad ( string $input , int $pad_length [, string $pad_string = " " [, int $pad_type = STR_PAD_RIGHT ]] )
echo str_pad('125', 'p6ll', 0, STR_PAD_LEFT);
php5.3:
PHP Warning: str_pad() expects parameter 2 to be long, string given in Command line code on line 1
php5.2:
125
2. clearstatcache() 默认不再清除缓存的 realpath
php5.3中的函数api是:
void clearstatcache ([ bool $clear_realpath_cache = false [, string $filename ]] )
php5.2中的函数api是:
void clearstatcache ([ bool $clear_realpath_cache = true [, string $filename ]] )
这个函数的意义是清除file的缓存,有一些函数会带来file的缓存,比如is_file ,file_exists等。不删除路径的话,在使用的过程中,就要考虑文件是否存在了,因为文件在使用的过程中,可能会删除的。
3.realpath() 现在是完全与平台无关的. 结果是非法的相对路径比如 __FILE__ . "/../x" 将不会工作.
解读:realpath在不同的版本,得到的路径是不一样的。例子如下:
chdir('/tmp/test/');
echo realpath('./');
php5.3:运行目录:/data/website/qqtalkweb/htdocs/syb
结果: /tmp/test
php5.2:运行目录:/root
结果: /root
4. call_user_func() 系列函数即使被调用者是一个父类也使用 $this.
解读:这个 call_user_func 和 call_user_func_array 序列函数调用时,被调用者即使是一个父类也是使用$this。
5.数组函数 natsort(), natcasesort(), usort(), uasort(), uksort(), array_flip(), 和 array_unique() 将不再接受对象作为参数. 在将这些函数应用于对象时, 请首先将对象转换为数组.
解读:这个很好理解,就是这些函数不接受对象的参数,如果是对象,请先将参数转换为数组。
6.按引用传递参数的函数在被按值传递调用时行为发生改变。 此前函数将接受按值传递的参数, 现在将抛出致命错误。之前任何期待传递引用但是在调用时传递了常量或者字面值 的函数, 需要在调用前改为将该值赋给一个变量。
解读:这个按照字面意思理解就好了
7.新的 mysqlnd 库需要使用 MySQL 4.1 新的 41 字节密码格式。继续使用旧的 16 字节密码将导致 mysql_connect() 和其它类似函数 抛出 "mysqlnd cannot connect to MySQL 4.1+ using old authentication." 错误。
解读:字面理解就好
8.新的 mysqlnd 库将不再读取 MySQL 配置文件(my.cnf/my.ini), 这与旧版本的 libmysql 库不同. 如果你的代码依赖于这些配置 文件, 你可以使用 mysqli_options() 显式地加载它。注意, 这意味着如果 PDO 中的 MySQL 支持使用了 mysqlnd 进行编译,PDO 特有常量 PDO::MYSQL_ATTR_READ_DEFAULT_FILE 和PDO::MYSQL_ATTR_READ_DEFAULT_GROUP 将是未定义的。
解读:这个多说一句,php5.3后,php自带了mysql的驱动,解决了php和mysql的多个license的问题。使用mysqlnd 作为的php mysql,mysqli,pdo的驱动的话,需要显式来定义。比如:--with-mysql=shared,mysqlnd --with-mysqli=shared,mysqlnd --with-pdo-mysql=shared,mysqlnd ,在编译php的是,需要这样来定义 options。这样的话,就不需要mysql的配置文件 my.ini 了,并且不再使用 libmysql 作为php连接mysql的驱动
9.SplFileInfo 及其相关目录类会移除末尾的 /.
解读:这个直接从字面意思理解就好了。
10. __toString 魔术方法不再接受参数.
解读:从字面意思来解读
11.魔术方法 __get, __set, __isset, __unset, and __call 应该总是公共的(public)且不能是静态的(static). 方法签名是必须的。
解读:从字面意思来解读
12.现在 __call 魔术方法在访问私有的(private)和被保护的(protected)方法时被调用
解读:从字面意思来解读
13.函数内 include 或者 require 一个文件时,文件内 将不能使用 func_get_arg(), func_get_args() 和 func_num_args() 函数。
解读:从字面意思来解读
14.新增了一个包裹在 MHASH 扩展外面的仿真层。但是并非所有的算法都涉及到了,值得注意的是 s2k 哈希算法。这意味着 s2k 哈希算法在 PHP 5.3.0 中不再可用。
解读:从字面意思来解读。另外这个用得很少的
1. 不再支持 安全模式 。任何依赖安全模式的应用在安全方面都需要进行调整。
解读:安全模式 在5.3中引入,在5.4就被删除了,说明有很大的缺陷。试图帮php解决共享服务器的问题。从php方面去解决操作系统方面的问题,不现实。具体请参考官方说明 安全模式
2.移除 魔术引号 。为避免出现安全问题,依赖此特性的应用可能需要升级。 get_magic_quotes_gpc() 和 get_magic_quotes_runtime() 现在总是返回 FALSE 。调用 set_magic_quotes_runtime() 将产生一个 E_CORE_ERROR 级别的错误。
当打开时,所有的 '(单引号),"(双引号),\(反斜线)和 NULL 字符都会被自动加上一个反斜线进行转义。这和 addslashes() 作用完全相同。
解读:这个是php有一个魔术引号的配置,如果我配置成功的话,会将 '(单引号),"(双引号),\(反斜线)和 NULL 字符 自动加收昂一个反斜线来转义。但是这样会增加很多额外的操作,使得开发者不方便操作原始数据。5.4移除了这个功能。主要影响的函数是:magic_quotes_gpc,magic_quotes_runtime,magic_quotes_sybase 魔术引号
3.register_globals 和 register_long_arrays php.ini 指令被移除。
解读:
register_globals 和 register_long_arrays都是php.ini 中的一个配置。
register_globals 可设置为ON和Off
1:当register_globals=Off
接收数据的程序应该用根据表单form传值的方法来决定。GET:用$_GET['name']、$HTTP_GET_VARS['name']来接收值;POST:当form用POST提交数据$_POST['name']、$HTTP_POST_VARS['name']来接收值;
2:当register_globals=On
接收数据的程序可以直接使用$user_name和$user_pass的这种类似访问变量的方式得到值。register_long_arrays 是来设置 标识 $HTTP_*_VARS 这类的变量(On)
由于$HTTP_*_VARS这种变量已经过时,PHP手册中明确表示反对使用,因此如果程序中还有这类变量建议更改为新的PHP 超全局变量。
$HTTP_GET_VARS -> $_GET
$HTTP_POST_VARS -> $_POST
$HTTP_COOKIE_VARS -> $_COOKIE
$HTTP_POST_FILES -> $_POST
4.调用时的引用传递 被移除。
解读:php之前如果方法定义了一个传引用的参数,在调用时是可以传 &的,但在5.4,这种传参的方式就被移除了。例如:
function foo(&$var)
{
$var++;
}
$a=5;
foo($a);// $a is 6 here
不需要这样调用 foo(&$a);
5.break 和 continue 语句不再接受可变参数( 比如: break 1 + foo() * $bar; )。
解读:从字面意思来解读。一个例子说下:
像类似 break 2; 这样的固定参数仍可使用。受此变化影响,不再允许出现 break 0; 和 continue 0; 。
6.在 日期与时间扩展 中,不再支持时区使用 TZ(TimeZone)环境变量设置。必须使用 date.timezone php.ini 配置选项或 date_default_timezone_set() 函数来指定时区。PHP 将不再尝试猜测时区,而是回退到“UTC”并发出一条 E_WARNING 错误。
解读:这个是关于时间的,从字面意思来理解就好了。
7.非数字的字符串偏移量,比如 $a['foo'] 此处 $a 是一个字符串,现在使用 isset() 时返回 false,使用 empty() 时返回 true,并产生一条 E_WARNING 错误。偏移量类型是布尔和 null 则产生一条 E_NOTICE 错误。 数字字符串(比如 $a['2'] )仍像以前一样运行。注意像类似 '12.3' 和 '5 foobar' 这样的偏移量将被视为非数字并产生一条 E_WARNING 错误,但因为向后兼容的原因它们会被分别转换成 12 和 5 。
解读:下列代码返回不同的结果。 $str='abc';var_dump(isset($str['x'])); // 在 PHP 5.4 或更新版本返回 false,但在 PHP 5.3 或更低版本返回 true
8.数组转换成字符串将产生一条 E_NOTICE 级别的错误,但返回的结果仍是字符串 "Array" 。
解读:其实就是数组不能转换为字符串了。
9.NULL 、FALSE 、或 一个空字符串被添加成一个对象的属性时将发出一条 E_WARNING 级别的错误,而不是 E_STRICT 。
解读:这个意思是放松了对 null 等的对象属性的限制
10.现在参数名使用全局变量将会导致一个致命错误。禁止类似 function foo($_GET, $_POST) {} 这样的代码。
解读:其实不能使用全局的函数名来做函数的参数
11.Salsa10 和 Salsa20 哈希算法 被移除。
解读:去掉了5.3支持的哈希算法
12.当使用两个空数组作为参数时, array_combine() 现在返回 array() 而不是 FALSE 。
解读:这个我觉得其实php5.4对5.3的bug修复
13.htmlentities() 将像 htmlspecialchars() 一样处理亚洲字符集,这是以前 PHP 版本的处理情况,但现在将会发出一条 E_STRICT 错误。
解读:从字面理解就好了
14.强烈建议不要再使用 eregi() ,此特性在最新版本中被移除。
解读:eregi 系列函数是一些匹配正则表达式用的。在5.4中将不再支持,请使用新的方式。
1.不再支持 Windows XP 和 2003
解读:这个很简单,xp 和 2003 已经进入历史的长河了,新的版本没有花大力气去支持他了。
2.pack() 和 unpack() 函数的变化
pack() 现在支持“Z”格式代码,其表现的行为与“a”相同。
unpack() now support the "Z" format code for NULL padded strings, and behaves as "a" did in previous versions: it will strip trailing NULL bytes.
支持null填充的z的格式,且其行为类似上一个版本中的“a”:清除后面的 NULL 字节。
unpack() now keeps trailing NULL bytes when the "a" format code is used. 当使用a格式的时候,会保留后面的 NULL字节
unpack() now strips all trailing ASCII whitespace when the "A" format code is used. 当使用A格式的时候,会清除最后的所有的ASCII空格字符
3.移除 PHP logo GUIDs
解读:其实主要删除了一些guid的函数,主要是以下的一些函数:
php_logo_guid() 此函数能够返回用于显示 PHP logo 内置图像的 ID
php_egg_logo_guid()
php_real_logo_guid()
zend_logo_guid()
解读:在 PHP 5.6 之前的版本中,为类定义数组类型的属性时, 如果数组中同时使用了显式数组键和隐式数组键,并且显式的键和隐式的序列键相同, 那么数组的键将被覆盖。例如:
class C {
const ONE = 1;
public $array = [
self::ONE => 'foo',
'bar',
'quux',
];
}
var_dump((new C)->array);
?>
结果如下:
5.5:
array(2) {
[0]=>
string(3) "bar"
[1]=>
string(4) "quux"
}
5.6:
array(3) {
[1]=>
string(3) "foo"
[2]=>
string(3) "bar"
[3]=>
string(4) "quux"
}
2. 严格的 json_decode()
对于 JSON 字面量 true,false 和 null,如果不采用小写格式,将会被 json_decode() 函数拒绝, 同时相应的设置 json_last_error()。 在之前的版本中,json_decode() 函数可以接受这些字面量的 全部大写或者大小写混写的格式。
此变更仅会影响传入到 json_decode() 中的 JSON 格式无效的情况, 有效的 JSON 输入不会受到影响并且能够正确解析。
3.当使用 SSL/TLS 的时候,流封装器默认验证端点证书和主机名
4.GMP 资源现为对象
GMP 资源现为对象。 GMP 扩展中的基于函数的 API 实现不受影响, 只有在代码中使用 is_resource() 或类似函数 来显示检测是否资源类型的代码才会受到影响。
5.Mcrypt 函数需要有效长度的密钥和初始向量
mcrypt_encrypt(),mcrypt_decrypt(), mcrypt_cbc(),mcrypt_cfb(), mcrypt_ecb(),mcrypt_generic() 以及 mcrypt_ofb() 函数不再接受无效长度的密钥和初始向量, 对于需要初始向量的分组加密模式,如果不提供初始向量,函数调用将会失败。
6.cURL 文件上传
必须先设置 CURLOPT_SAFE_UPLOAD 为 FALSE 才能够使用 @file 语法来上传文件。 建议使用 CURLFile 类来上传文件。
具体php5.6对5.5的不兼容的地方请见:http://php.net/manual/zh/migration56.incompatible.php。整体来将,php5.5到5.6的过程是一个更加规范的过程。
以上就是从php5.2升级到php5.3,5.4,5.5,5.6需要注意事项。