PHP 5.5.x->PHP 5.6.x
新增
- 使用表达式定义常量。
- 使用...运算符定义变长参数函数。
- 使用右连接运算符**来进行幂运算。
- 支持大于2GB的文件上传。
- 使用hash_equals()函数,以恒定的时间消耗来进行字符串比较,以避免根据精确测量执行时间反推出密码的时序攻击。
- __debugInfo(),当使用var_dump()输出对象时,可以用来控制要输出的属性和值。
- 对SSL/TLS的支持进行大幅度提升,包括默认启用端点验证选项来支持证书指纹比对,以避免TLS重新协商攻击。
- pgsql拓展支持以异步方式连接数据库和执行查询,即可以使用非阻塞的方式与PostgreSQL数据库进行交互。
修改
- 只有设置CURLOPT_SAFE_UPLOAD为false的情况下,才能使用@file语法上传文件,因此最好采用CURLFile代替。
- 使用数组标识符为类定义数组类型的属性时,数组的键不会被覆盖。可以理解为数组里显式键和隐式序列键相同时,数组的键不会相互覆盖。
- 对于JSON字面量true,false和null,必须采用字母全部小写的形式。
- 一些Mcrypt函数需要设置有效长度的密钥和初始向量,不再接受无效长度的密钥和初始向量。
废除
- 废止从不兼容的上下文调用方法。
- 废弃了iconv和mbstring配置选项中和编码相关的选项,建议使用default_charset。
PHP 5.6.x->PHP 7.0.x
新增
- 对于标量类型声明,不论是强制(默认)模式还是严格模式,都可以使用浮点数、字符串、布尔值、整数 类型的参数类型。
- 对返回类型声明的支持,返回类型声明指明了函数返回值的类型。
- null合并运算符(??),作用相当于简化三元表达式。如果变量存在并且值不为null,则返回自身值,否则就返回它的第二个操作数。
- 组合比较符<=>,用于比较两个表达式。第一个表达式的值大于、等于、小于第二个表达式的值时,对应的返回值依次是1、0、-1。
- 通过define()可定义数组类型的常量。
- 支持通过new class来实例化一个匿名类,可用来替代一些“用后即消除”的完整类定义。
- Closure::call()可以简洁地暂时绑定一个方法到对象上闭包并调用它。
- 为unserialize()提供过滤,可通过白名单的方式来防止恶意代码的注入,以更安全的方式解包不可靠的数据。
- IntlChar类旨在公开出更多的ICU(开源项目)功能,这个类自身定义了很多静态方法用来操作Unicode字符集。若使用此类,需要先安装Intl拓展。
- 从同一个namespace引入的类、常量和函数现在可以用单个use语句一次性导入。
- 生成器可以返回表达式,可通过调用Generator::getReturn()来获取生成器返回值。
- 在最外层生成中使用yield from 就可以把一个生成器自动委派给其它的生成器,Traversable(遍历)对象或者array。
- intdiv()函数用于整数的除法运算。
- session_start()可以接受一个数组作为参数,覆盖php.ini里的会话配置选项。
- 通过preg_replace_callback_array()函数,可以使用一个关联数组对每个正则表达式注册回调函数。
- random_bytes()和random_int()用来产生高安全级别的随机字符串和随机整数。
修改
- dirname()增加了可选的第二个参数 depth,用于获取当前目录向上depth级的父目录名称。
- xml_parser_free()不再足以释放解析器资源,如果它引用了一个对象,而这个对象引用了一个解析器资源,在这种情况下,需要额外地设置取消解析器。
- 在PHP7中,很多运行错误都转为异常来处理了,这些异常继承自Error类,此类实现了Throwable接口(所有异常都实现了这个基础接口)。这也就意味着,当程序运行发生错误时,以前的代码里如果没有捕获Error类异常,那么一些关于错误处理的代码将触发不了,这会导致程序运行很严重的错误。
- 对变量、属性和方法的调用将严格遵守从左到右的解析顺序,如果需要兼容旧的程序,需要使用大括号。
- list()不支持空的赋值,且在赋值时按照变量被定义的顺序来赋值,而非反过来的顺序。
- list()不能解开字符串变量,可以用str_split函数来代替。
- foreach不改变内部数组指针。
- foreach通过引用遍历时,有更好的迭代特性。例如在迭代中添加一个迭代值到数组中。
- 一个八进制字符里如果含有无效数字(如8),这样的八进制字符将产生解析错误,而不是静默删节。
- 以负数形式进行的位移运算符将抛出异常,而不是返回0。
- 除以0将返回一个由IEEE754指定的浮点数:+INF、-INF或者NAN,而不是抛出一个警告错误并返回false。
- 十六进制字符串不被视为数字,可以用filter_var()函数检查一个字符串是否包含十六进制数字,并将其中的十六进制数字字符串转换为整数。
- yield变更为右联接运算符。
- 在函数定义中,不可以包含两个或多个同名参数。
- 当在函数代码中使用func_get_arg()或者func_get_args()方法查看函数参数值,或者用debug_backtrace()方法查看回溯跟踪,以及在异常回溯中所看到的函数参数值是当前值,而非传入函数时的原始值。
- 在ini文件里,不支持#表示注释,需要用;来表示注释。
- JSON拓展已被JSOND拓展取代,对于数值处理要注意数值不能以点号.结束,科学计数法e前面一位字符不可以是点号.,如3.e3应该改写为3.0e3或者3e3。另外,空字符串不被当作有效的JSON字符串。
- 在数值溢出时,内部函数会失败。例如将数值很大的浮点数转换为整数,无法以整数表达时,将会报错并返回null,而不是自动将整数截断不报错误。
- 由于内部排序算法进行了提升,会导致对比时视为相等元素的排序顺序不稳定。
- declare(ticks)指示符不再泄漏到不同的编译单元里。
- listen端口同时监听IPV4地址和IPV6地址。
废除
- preg_replace()不再支持\e(可以把匹配来的字符串当作正则表达式来用),需要用preg_replace_callback函数来替代
- 所有的ereg系列函数被移除,PCRE作为其替代品。
- 一些废弃的mcrypt_开头的函数被移除。
- 所有ext/mysql函数被移除。
- 移除了类似ASP的标签和Script PHP标签。例如<% %>、<%= %>、<script language=”php”>。
- PHP4风格的构造函数(方法名和类名一样)将被弃用。
- 废弃了静态调用未声明成static的方法。
- 废弃了password_hash()函数里的盐值选项,阻止开发者生成自己的盐值(通常更不安全),该函数将自行生成密码学安全的盐值。
- 废弃了capture_session_meta内的SSL上下文选项,可以通过stream_get_meta_data()来获取SSL元数据(metadata)。
PHP 7.0.x->PHP 7.1.x
新增
- 可为空(Nullable)类型。参数及返回值的类型可以在其类型前加上一个?表示可空,当启用这个特性时,传入的参数或者函数返回的结果要么是指定类型,要么是null。
- 新的返回值类型void。返回值生命为void类型的函数需要省去返回值(去掉return或者return;), 注意这里返回null也不允许,但是如果企图获取一个返回值类型为void的函数返回值时,会得到一个null,并且不会因此产生警告。
- 短数组语法([])作为list()语法的一个备选项,可用于将数组的值赋给一些变量(包括在foreach中)。list()和[]已支持在其内部指定键名,这意味着可以将任意类型的数组赋值给一些变量。
- 支持设置类常量的可见性。
- 引入了iterable伪类(与callable类似)。它可以被用在参数或者返回值类型中,代表接受一个数组或者实现了遍历接口的对象。至于子类,当iterable伪类用作父类的参数类型时,子类可以收紧父类的iterable参数类型为数组类型或者实现了遍历接口的对象类型。另外,子类可以将返回值由父类返回值的数组类型或者实现了遍历接口的对象类型,拓展为iterable伪类类型。
- 多异常捕获处理。一个catch语句块可以通过管道字符|来实现多个异常的捕获,这在需要同时处理来自不同类的不同异常时很有用。
- ext/openssl 支持了AEAD(模式GCM和CCM)。方式是给openssl_encrypt()和openssl_decrypt() 添加额外的参数。
- Closure::fromCallable()静态方法可把callables转为闭包。
- 异步信号处理。pcntl_async_signals()被引入,用于启用无需ticks(开销大)的异步信号处理。
- 对服务器推送的支持已经加入到了CURL拓展中,这个可以通过curl_multi_setopt()函数与新的常量CURLMOPT_PUSHFUNCTION来调节。添加进来的CURL_PUSH_OK和CURL_PUSH_DENY两常量可用来批准或拒绝服务器推送回调的执行。
- 支持为负的字符串偏移量。
//代码示例
var_dump("abcdef"[-2]); //string(1) “e”
var_dump(strpos("aabbcc", "b", -3)); //int(3)
var_dump("abcdef"[-60]); //string(0) “”
var_dump(strpos("aabbcc", "b", -5)); //int(2)
修改
- 当参数传递不足时将抛出错误,这仅对用户定义的函数生效,内置函数不生效。
- 在不完整的对象上不调用析构方法(类的对象被销毁时自动被调用的方法__destruct)。
- parse_url()提供了更加严格的限制,例如对RFC3986的支持。
- file_get_contents()接受负数作为搜索偏移量,前提是流上下文必须是可搜索的。
- tempnam()会在退回使用系统临时目录的时候,产生警告。
- json_encode()增加了新的选项:JSON_UNESCAPED_LINE_TERMINATORS,这个选项可以在指定值为JSON_UNESCAPED_UNICODE的时候对于U+2028和U+2029这两个字符不进行转义。
- PDO::LastInsertId()在用于PostgreSQL数据库时,如果当前会话(连接到PostgreSQL的数据库连接)尚未调用过nextval,那么此方法会触发一个错误。
- Session ID不在生成时进行哈希。
废除
- mcrypt拓展被废弃,并被OpenSSL所取代。
PHP 7.1.x->PHP 7.2.x
新增
- 新的对象类型,object,引进了可用于逆变(contravariant)参数输入和协变(convariant)返回任何对象类型。
- 拓展文件不需要通过文件加载进行指定,可以在php.ini配置文件里进行启用,也可以使用dl()函数(运行时载入一个php拓展)进行启用。
- 允许重写抽象方法。当一个抽象类继承另一个抽象类时,继承后的抽象类可以重写被继承的抽象类里的抽象方法。
- PDO的字符串类型已经拓展为支持国际化的字符集。
- 为ext/PDO新增额外的模拟调试信息。PDOStatement::debugDumpParams()方法已更新,当发送sql到数据库时,在一致性、行查询(包括替换绑定占位符)将会显示调试信息。这一特性已经加入到模拟调试中(模拟调试打开时可用)。
- ext/LDAP(轻量目录访问协议)拓展新增了EXOP(extended operation,拓展操作)支持。
- ext/sockets拓展 具备了查找地址信息的能力,且可以连接到地址,进行绑定和解析。
- 拓展了参数类型。重写方法和接口实现的类型现在可以省略了,不过这仍然符合LSP(里氏替换原则),因为现在这种参数类型是逆变的。
- 命名空间可以使用尾随逗号进行分组引入。
//代码示例:
use Namespace\Content\{
Content1,
Content2,
Content3
};
?
修改
- 阻止了number_format()返回负零。
- 将数组转换为对象,或者将对象转换为数组时,数字键得到了更好的处理。
- get_class()函数不接受null参数。
- 计算非可数(non-countable)类型时,发出警告。
- ext/hash从资源变成对象。要注意旧版本里相应的is_resource()检查改成is_object()检查。
- SSL/TSL的默认选项的改进。
- gettype()对闭包资源的返回值会是“resource (closed)”,而非字符串“unknown type”。
- object变更为强制保留字,禁止在任何接口和类的名称里使用它。
- 使用默认参数的array_unique()会将不重复的原数组元素添加到一个新数组里,这可能改变原数组元素的键值。
- parse_str()第二个参数已改为必填项,因为安全隐患问题(不加第二个参数会导致查询字符串参数导入当前符号表)。更改后查询字符串转为了Array。
- utf8_encode()和utf8_decode()已作为字符串处理函数移到标准拓展中,不再需要去启用XML拓展后才能使用。
- imagegd()以真彩色存储真彩色图像,而不是转化为调色板图像。
- 传递给session_module_name()函数的模块名不允许为“user”,会抛出一个异常错误。
废除
- sql.safe_mode ini设置项已被移除。
- GD拓展库里的png2wbmp()和jpeg2wbmp()已被废弃。
- __autoload()方法已废弃,因为和spl_autoload_register()方法相比功能较差(因为无法链式处理多个__autoloader),而且也无法在两种autoloading样式中配合使用。
- track_errors ini设置和$php_errormsg变量已废弃,因为提供了更好的方式:error_get_last()。
- create_function()函数(有安全隐患问题,它是eval()的瘦封装器)已被废弃,更好的选择是匿名函数。
- mbstring.func_overload ini设置已废弃,因为这个设置会影响环境中的字符串系列函数,带来相互操作中的问题。
- (unset)类型强制转化已废弃,结果总是null。
- gmp_random()函数已废弃,可使用更好方式产生随机数:GMP拓展中的gmp_random_bits()和gmp_random_range()。
- each()函数被废弃,使用此函数遍历时,比普通的foreach()更慢,而且给新语法的变化带来实现问题。
- assert()字符串参数要求它能被eval()执行,考虑到可能被执行远程代码,所以废弃了assert()参数的字符串类型声明,最好提供bool数据类型的参数。
- 错误处理器里的$errcontent参数被废弃。代替做法:调试器应该自己取回错误站点里的本地变量。
- MCrypt拓展从内核移到了PECL,由于mcrypt库自2007年来未见任何更新,所以不建议使用mcrypt库。代替品可以用OpenSSL,也可以用Sodium。
PHP 7.2.x->PHP 7.3.x
新增
- 更灵活的HereDoc和NowDoc语法,支持闭合标记符的缩进,且不强制闭合标记符的换行。但要注意闭合标记符不要与正文中的字符串同名,避免出现语法错误和解析错误。
- 数组解构(结构化赋值)现在支持使用语法进行引用赋值。这对list()也同样支持。
- instanceof接受文字作为第一个操作数,但这种情况下结果总是返回false。
- 允许在函数和方法调用后面使用逗号。
- FastCGI进程管理器添加了log_limit、log_buffering等新选项以自定义FPM日志记录。
- 对LDAP控件的完全支持已添加到LDAP查询功能和ldap_parse_result()。
- 多字节字符串函数已可以正确处理大于2GB的字符串。
- 多字节字符串拓展的性能已得到全面显著提高,尤其是大小写转换功能。
- Arrayaccess(使对象像数组一样被访问)整数字符串键值得到严格解释,整数字符串文字将不导致隐式转换为整数,例如$obj[“123”]将调用$obj->offsetGet(“123”);而非$obj->offsetGet(123);
修改
- getimagesize()和相关函数已将BMP图像的mime类型报告为image/bmp,而不是image/x-ms-bmp,因为前者已在IANA(互联网数字分配机构)注册。
- 默认情况下禁用rsh/ssh登录,如果要启用它们,需要使用imap.enable_insecure_rsh。注意IMAP库在将邮箱名称传给rsh/ssh命令之前不会对其进行过滤,因此在启用rsh/ssh的情况下将不受信任的数据传递给此函数是不安全的。
- 出于安全方面原因,传入cookie的名称不进行url解码。
- FTP默认传输模式已更改为二进制传输模式,而不是ASCII传输方式。
- setcookie和setrowcookie函数接受$option数组参数。
- getallheaders(获取全部HTTP请求头信息)函数已可用。
- 垃圾回收机制有所改进,带来很大的性能提升。
- 涉及SimpleXML对象的数学运算已将文本当作int或float,以更合适的方式处理,而非无条件地当作整数处理。
废除
- 大小写不敏感的常量声明已废弃。
- 废弃在命名空间里使用assert命名函数,因为assert()函数属于引擎特殊处理的情况。
- image2wbmp()函数已废弃。
- 已废弃:将一个非字符串内容传递给字符串搜索函数。替代为所有待搜索的内容都会被当作是字符串,而不是ASCII编码值。如果需要依赖这个已被废弃的特性,需要将传入的非字符串内容先显式转换为字符串类型,或者显式地调用chr()。
PHP 7.3.x->PHP 7.4.x
新增
- 类的属性支持添加指定的类型声明。
- 支持完整的协变和逆变。协变使子类能比父类的返回类型更具体,逆变使子类能比父类接受的参数类型更宽泛。
- 合并空运算符赋值,??=后面可以接函数名。
- 数组展开操作中。可以用...接数组名作为另一个数组的数组项。
- 数字文字可以在数字之间包含下划线。
- 弱引用允许保留对对象的引用,但不会阻止对象被销毁。弱引用是通过变量来创建的,指向的是原始对象的符号表,可以让垃圾回收器正常的回收,可以避免循环引用带来的内存泄露问题,能让引用表现为类似C语言里的指针操作。
- 允许__tostring()方法抛出异常,而非阻止程序继续运行的错误。
- 如果拓展是针对libcurl>=7.56.0创建的,那么CURLFile不仅支持文件名的处理,也支持流封装器的处理。
- FFI拓展。该拓展提供了一种调用本地函数,访问本地变量,及创建和访问C库中定义的数据结构的简单方法。
- 添加了IMG_FILTER_SCATTER图像过滤器以将散列过滤器应用于图像。
- mb_str_split()函数。str_split()用于将字符串分隔到数组中,但它仅可以分割字母和数字,新增的mb_str_split()函数是对其的补充,可以用来分割任何指定编码的字符串。
- 缓存预加载特性。注意性能和内存之间的最佳权衡可能因应用程序而异,“预装一切”可能是最简单的策略,但不一定是最佳策略。
- 可以在sql查询中转义问号以避免其被当作参数占位符,写作??允许向数据库发送一个问号,例如PostgreSQL JSON键缓存里存在问号时。
- PDOStatement::getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT)允许检查语句是否为只读,即它是否不修改数据库。
- strip_tags第二个参数(允许通过的标签名单)已可以传入一个数组。
- 添加了自定义对象序列化的新机制,它使用了两个新的魔术方法:__serialize()和__unserialize()。新的序列化机制取代了Serializable接口。
- 为array_key_exists添加了一个专门的VM opcache优化,如果该函数可以被静态解析,则可以提高该函数的性能。如果在项目中使用命名空间,可能需要使用\array_key_exists()来显式导入该函数。
- 箭头函数提供了更简洁的定义函数的方法。
//代码示例:
$x=1;
$y=2;
$fn1=fn($z)=>$x+$z;
$fn3=fn($c)=>fn($d)=>$c*$d*$y;
var_export($fn1(3)); //4
var_export($fn3(4)(5)); //40
修改
- get_declared_classes()函数在匿名类未实例化时,不返回匿名类的名称。
- fn成了保留关键字,不可以作为函数名和类名,但是仍然可以作为方法名和类的常量名。
- fread()和fwrite()在操作失败时将返回false,而非空字符串或0。
- token_get_all()为意外字符发出T_BAD_CHARACTER警告,而不是在令牌流中留下漏洞。
- 不推荐使用$this来解绑非静态闭包里的$this。
- imagescale()已支持将-1作为$new_width传递来使图像缩放到指定高度时保持纵横比。
- 哈希拓展已不能被禁用,它已成为PHP里很重要的组成成分,就像是日期拓展一样。
废除
- MySQLi嵌入式服务器功能已被删除。未记录的mysqli::$stat属性已被删除,以支持mysqli::stat()。
- 导入类型库的大小写不敏感的常量注册已被废弃。
- 捆绑的libzip库已被删除。需要一个系统libzip>=0.11来构建zip拓展。
PHP 7.4.x->PHP 8.0.x
新增
- 命名参数。命名参数允许根据参数名而不是参数位置向函数传参,这使得参数的含义自成体系。命名参数通过在参数名前加冒号来传递,允许使用保留关键字作为参数名,参数与顺序无关,并允许任意跳过默认值。参数名必须是一个标识符,不允许动态指定。
- 注解功能。注解的功能使得代码中的声明部分都可以添加结构化、机器可读的元数据。注解的目标可以是类、类常量、属性、方法、函数、参数。通过反射API可在运行时获取注解中所定义的元数据。因此注解可以成为直接嵌入代码的配置式语言。注解使用的一个简单例子是:将接口(interface)里的可选方法改用注解实现。
- 构造器属性提升。构造器里的参数可以相应提升为类的属性,注意对象属性的类型不可以为callable,避免为引擎带来混淆,因此提升的参数也不能是callable。
- 联合类型。联合类型接受多个不同的类型作为参数,声明联合类型的语法是T1|T2|...。?T语法将当作是联合类型T|null的简写。注意null类型允许在联合类型里使用,但是不能作为一个独立的类型使用。
- match表达式。match表达式与switch表达式相似,但是match表达式里是严格比较(===),一个match分支只能有一个表达式,每个分支都会有一个返回值,match的匹配表达式里可以用逗号来分割多个表达式。对于match表达式,传入的参数必须存在与表达式匹配的条件或default要处理的条件,否则会报异常。match末尾的大括号后面要用分号;结束。
- Nullsafe操作符(?->)。类属性和方法可以通过nullsafe操作符访问。对象引用解析为null时不抛出异常,而是返回null,如果是链式调用中的一部分,则剩余链条会直接跳过。此操作的结果类似于在每次访问前用is_null()函数判断一下属性和方法是否存在,但代码更加简洁。注意仅当null是属性或者方法可能返回的预期值的情况下,才推荐用Nullsafe操作符。如果业务中需要明确指出错误,那么还是用抛出异常的方案来处理更好。
- WeakMap类。WeakMap类接受对象作为键的映射(或字典),WeakMap键中的对象不影响对象的引用计数。它的主要用途是构建源自对象的数据缓存,这些数据不需要比对象存在更长的时间。WeakMap类实现了ArrayAccess(数组式访问)、Iterator(迭代器)和Countable(可计数),所以在大多数情况下,它可以以与关联数组相同的方式使用。
- static(如“后期静态绑定”)可以用作返回类型。
- 可以通过$object::class来获取类名,与get_class($object)返回结果一致。
- HashContext对象已可以序列化。
- new,instanceof(判断一个对象是否是某个类的实例,或者实现了某个接口)可用于任何表达式。用法为 new (expression) (...$args)和$obj instanceof (expression)。
- 支持mixed(值可为任何类型)类型。
- 对加密消息语法(CMS)的支持。由用于加密、解密、签名、验证和读取的函数组成。
- 可选的压缩、加密功能已列入phpinfo中。
- opcache拓展新增了即时编译(JIT)的支持。
- PhpToken向标记器添加了一个基于对象的接口,它提供了更统一和符合功效学的表示,具备更高的内存效率和更快的速度。
修改
- 数字与非数字类型的字符串非严格比较(==)时,将把数字转换为字符串,然后比较两个字符串。数字与数字类型的字符串非严格比较(==)时,则可理解为是把数字类型的字符串转为数字,然后比较两个数字。例如0==””?将返回false,而不是true。
- 断言(Assertion)失败已默认抛出异常,如果需要改回之前的行为,需要在ini里设置assert.exception=0。
- 与类名相同的方法名不被当作构造方法,类的构造方法需用__construct()。
- 不允许通过静态调用的方式调用非静态方法。因此is_callable()在检查具有类名的非静态方法时会失败(必须检查对象实例)。
- 已删除对对象使用array_key_exists()函数的能力。可以使用isset()或者property_exists()函数替代。
- 在没有父级的类中使用父级声明会造成严重的编译时错误。
- @运算符不消除严重错误(E_ERROR\E_CORE_ERROR\E_COMPILE_ERROR\E_USER_ERROR\E_RECOVERABLE_ERROR\E_PARSE)。使用@时期望error_reporting为0,错误处理函数应调整为使用隐式检查。注意在生产环境中不要显示出错误信息,因为这可能导致信息泄露,需确保display_errors=Off与错误记录一同使用。
- #[不被解释为注释的开始,因为此语法已用于属性。
- data://流封装器不支持写入。
- 连接运算符.的优先级相对于位移、加法、减法的优先级发生了变化。
//代码示例:
echo “sum: ”.$a+$b;//等同echo “sum: ”.($a+$b); 而不是 echo (“sum: ”.$a)+$b;
废除
- 过滤器string.strip_tags(此过滤器等同于用strip_tags处理所有的流数据)已废弃。
- read_exif_data()已被废除;应该改用exif_read_data()。exif_read_data()函数的作用是从一个图片文件里读取EXIF头信息,这样就可以读取数码相机产生的元数据。
|