PHP 70 新特性
https://www.php.net/manual/zh/migration70.new-features.php
https://www.php.net/manual/en/migration70.new-features.php
标量类型声明扩充
类型声明(类型提示)在原先支持“类名,接口,数组和回调类型”的基础上新增:
1、字符串(string); 2、整数 (int); 3、浮点数 (float); 4、以及布尔值 (bool)
返回值类型声明
增加了对返回类型声明的支持
null合并运算符
添加了null合并运算符 (??) 这个语法糖
$username = $_GET['user'] ?? 'nobody'; 等效 $username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
太空船操作符(组合比较符)
太空船操作符用于比较两个表达式。当$a小于、等于或大于$b时它分别返回-1、0或1。
<?php // 整数 echo 1 <=> 1; // 0 echo 1 <=> 2; // -1 echo 2 <=> 1; // 1 // 浮点数 echo 1.5 <=> 1.5; // 0 echo 1.5 <=> 2.5; // -1 echo 2.5 <=> 1.5; // 1 // 字符串 比如:strcmp($str1, $str2) 就可以使用以下方式简写 echo "a" <=> "a"; // 0 echo "a" <=> "b"; // -1 echo "b" <=> "a"; // 1
通过 define() 定义常量数组
define('ANIMALS', ['dog', 'cat', 'bird']);
匿名类
支持通过new class 来实例化一个匿名类,用来替代一些“用后即焚”的完整类定义
interface A { public function log(string $msg); } class B { } // 实例化匿名类 var_dump(new class implements A { public function log(string $msg){} }); var_dump(new class extends B{ });
Unicode codepoint 转译语法
接受一个以16进制形式的 Unicode codepoint,并用一个双引号或heredoc包围的 UTF-8 编码格式的字符串。 可以接受任何有效的 codepoint,并且开头的 0 是可以省略的
echo "\u{aa}"; // Output: a echo "\u{0000aa}"; // Output: a echo "\u{9999}"; // Output: 香 echo <<<EOF \u{9999} EOF; // Output: 香
Closure::call()
性能优化
为unserialize()提供过滤
旨在提供更安全的方式解包不可靠的数据。它通过白名单的方式来防止潜在的代码注入
// 将所有的对象都转换为 __PHP_Incomplete_Class 对象 $data = unserialize($foo, ["allowed_classes" => false]); // 将除 MyClass 和 MyClass2 之外的所有对象都转换为 __PHP_Incomplete_Class 对象 $data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]); // 默认情况下所有的类都是可接受的,等同于省略第二个参数 $data = unserialize($foo, ["allowed_classes" => true]);
IntlChar
新增加的 IntlChar 类旨在暴露出更多的 ICU 功能。这个类自身定义了许多静态方法用于操作多字符集的 unicode 字符。
printf('%x', IntlChar::CODEPOINT_MAX); // Output: 10ffff echo IntlChar::charName('@'); // Output: COMMERCIAL AT var_dump(IntlChar::ispunct('!')); // Output: bool(true) // 若要使用此类,请先安装Intl扩展
预期
预期是向后兼用并增强之前的 assert() 的方法。 它使得在生产环境中启用断言为零成本,并且提供当断言失败时抛出特定异常的能力。
老版本的API出于兼容目的将继续被维护,assert()现在是一个语言结构,它允许第一个参数是一个表达式,而不仅仅是一个待计算的 string或一个待测试的boolean。
ini_set('assert.exception', 1); class CustomError extends AssertionError {} assert(false, new CustomError('Some error message')); // Output:"Fatal error: Uncaught CustomError: Some error message"
PHP测试框架如:phpunit 中很常见
Group use declarations
从同一 namespace 导入的类、函数和常量现在可以通过单个 use 语句 一次性导入了。
// PHP 7 之前的代码 use some\namespace\ClassA; use some\namespace\ClassB; use some\namespace\ClassC as C; use function some\namespace\fn_a; use function some\namespace\fn_b; use function some\namespace\fn_c; use const some\namespace\ConstA; use const some\namespace\ConstB; use const some\namespace\ConstC; // PHP 7+ 及更高版本的代码 use some\namespace\{ClassA, ClassB, ClassC as C}; // 该示例在实际面向对象开发中可以也应该经常被套用 use function some\namespace\{fn_a, fn_b, fn_c}; use const some\namespace\{ConstA, ConstB, ConstC};
生成器可以返回表达式
此特性基于 PHP 5.5 版本中引入的生成器特性构建,它允许在生成器函数中通过使用 return 语法来返回一个表达式 (但是不允许返回引用值), 可以使用新方法 Generator::getReturn() 获取返回值,但该方法只能在生成器完成yielding values之后使用。
$gen = (function() { yield 1; yield 2; return 99; })(); // echo $gen->getReturn(); 致命错误,因为Generator::getReturn()方法只能在生成器完成yielding values之后使用 foreach ($gen as $val) { // 生成器被迭代(yielding value)两次 echo $val, PHP_EOL; } echo $gen->getReturn(), PHP_EOL; //Output:
1
2
99
生成器委派
现在,只需在最外层生成器中使用 yield from,就可以把一个生成器自动委派给其他的生成器,Traversable 对象或 array
function gen() { yield 1; yield 2; yield from gen2(); }
function gen2() { yield 3; yield 4; } foreach (gen() as $val) { echo $val, PHP_EOL; } // Output:
1
2
3
4
整数除法函数 intdiv()
新加函数 intdiv() 用来进行整数的除法运算。
var_dump(intdiv(10, 3)); // Output: 3 其结果相当于 intval(10 / 3) Or (int)(10 / 3),但是性能肯定是intdiv更好
Session会话选项
session_start()可以接受一个 array 作为参数, 用来覆盖 php.ini 文件中设置的 会话配置选项。
These options have also been expanded to support session.lazy_write, which is on by default and causes PHP to only overwrite any session file if the session data has changed, and read_and_close, which is an option that can only be passed to session_start() to indicate that the session data should be read and then the session should immediately be closed unchanged.
session_start([ 'cache_limiter' => 'private', // session在客户端的缓存方式,有nocache,private,private_no_expire,public;私有方式缓存 - private(比如:表单信息被保留,但在生存期内有效) 'read_and_close' => true, // 如果会话数据没有发生改变,那么 PHP 会在读取完session之后,立即关闭会话存储文件 ]);
preg_replace_callback_array()优化
在 PHP 7 之前,当使用 preg_replace_callback() 函数的时候, 由于针对每个正则表达式都要执行回调函数,可能导致过多的分支代码。 而使用新加的 preg_replace_callback_array() 函数, 可以使得代码更加简洁。
现在,可以使用一个关联数组来对每个正则表达式注册回调函数, 正则表达式本身作为关联数组的键, 而对应的回调函数就是关联数组的值。
新增两个跨平台的随机函数
random_bytes() 用来产生高安全级别的随机字符串
random_int() 用来产生高安全级别的随机整数。 更早版本时只能使用相对较安全的过渡函数 mt_rand(),rand()就更不用说了。
list() 函数bug修复
在之前版本中,list() 不能保证正确展开实现了 ArrayAccess 接口的对象, 现在这个问题已修复。(list 不是真正的函数,而是语言结构)
其他特性
允许在克隆表达式上访问对象成员,例如: (clone $foo)->bar()。 不需要 $newFoo = clone $foo; $newFoo->bar();分开两句来写
PHP 71 新特性
https://www.php.net/manual/zh/migration71.new-features.php
https://www.php.net/manual/en/migration71.new-features.php
可为空(Nullable)类型
参数以及返回值的类型可以通过在类型前加上一个问号使之允许为空。
function testReturn(): ?string // 限定函数只能返回string or null { }
Void 函数
一个新的返回值类型void被引入。 返回值类型声明为 void 的方法要么没有 return 语句,要么 return 直接接分号 。(return null;不合法; return ;合法)
Symmetric array destructuring 对称数组分解
短数组语法([])现在作为list()语法的一个备选项,可以用于将数组的值赋给一些变量(包括在foreach中),且支持键名。
$data = [ ["id" => 1, "name" => 'Tom'], ["id" => 2, "name" => 'Fred'], ]; // 等效,支持键名 list("id" => $id1, "name" => $name1) = $data[0]; ["id" => $id1, "name" => $name1] = $data[0]; // 等效,支持键名 foreach ($data as list("id" => $id, "name" => $name)) { // logic here with $id and $name } foreach ($data as ["id" => $id, "name" => $name]) { // logic here with $id and $name }
类常量可见性
现在起支持设置类常量的可见性。
class ConstDemo { const PUBLIC_CONST_A = 1; public const PUBLIC_CONST_B = 2; // 关键字const之前可以指定 public、potected等 protected const PROTECTED_CONST = 3; private const PRIVATE_CONST = 4; }
引入iterable 伪类
引入了一个新的被称为 iterable 的伪类 (与callable类似)。 这可以被用在参数或者返回值类型中,它代表接受数组或者实现了Traversable接口的对象。 对于子类,当用作参数时子类的参数类型可以将父类的 array 或 Traversable 声明拓展到 iterable;对于返回值类型,子类可以将父类的返回类型 iterable 收紧到 array 或 实现 Traversable 的对象。
class A { function iterator(Traversable $iter): iterable { foreach ($iter as $val) { // } } } // 合法的重写,编译通过 class B extends A { /** * @param iterable $iter 拓展参数类型 Traversable 到 iterable * @return array 收紧返回值类型 iterable 到 array */ function iterator(iterable $iter): array { foreach ($iter as $val) { // } } }
多异常捕获处理
一个catch语句块现在可以通过管道字符(|)来实现多个异常的捕获。 这对于需要同时处理来自不同类的不同异常时很有用。
try { // some code } catch (FirstException | SecondException $e) { // handle first and second exceptions }
支持为负的字符串偏移量
现在所有支持偏移量的字符串操作函数 都支持接受负数作为偏移量,包括通过[]或{}操作字符串下标。在这种情况下,一个负数的偏移量会被理解为一个从字符串结尾开始的偏移量。
var_dump("abcdef"[-2]); // Output: string (1) "e" var_dump(strpos("aabbcc", "b", -3)); // Output: int(3) $string = 'bar'; echo "The last character of '$string' is '$string[-1]'.\n"; // Output: The last character of 'bar' is 'r'.
ext/openssl 支持 AEAD模式
Support for AEAD (modes GCM and CCM) have been added by extending the openssl_encrypt() and openssl_decrypt() functions with additional parameters.
通过 Closure::fromCallable() 将callable转为闭包
Closure新增了一个静态方法,用于将callable快速转换为一个Closure 对象。
class Test { /** * @return Closure * @internal 该函数把私有方法 privateFunction 暴露给了开发者 */ public function exposeFunction() { return Closure::fromCallable([$this, 'privateFunction']); } private function privateFunction($param) { var_dump($param); } } $closure = (new Test)->exposeFunction(); $closure('some value'); // Output: string(10) "some value"
异步信号处理(参见declare)
一个新的名为 pcntl_async_signals() 的方法现在被引入, 用于启用无需 ticks (这会带来很多额外的开销)的异步信号处理。
pcntl_async_signals(true); // turn on async signals pcntl_signal(SIGHUP, function($sig) { echo "SIGHUP\n"; }); posix_kill(posix_getpid(), SIGHUP); // Output: SIGHUP
具体作用参考: https://www.gaojiufeng.cn/?id=238
HTTP/2 server push support in ext/curl
CURL扩展中增加了对服务器推送的支持(需要libcurl7.46及更高版本)。这可以通过 curl_multi_setopt() 函数和为常量 CURLMOPT_PUSHFUNCTION 选项设定一个推送回调(pushCallback)来激活该功能。
PHP71还新增了常量 CURL_PUSH_OK 和 CURL_PUSH_DENY ,用以表示批准或拒绝执行服务器推送的回调
Stream Context Options
The tcp_nodelay stream context option has been added. 新增一个流上下文选项:tcp_nodelay
// connect to the internet using the '192.168.0.100' IP and port '7000' $opts = array( 'socket' => array( 'bindto' => '192.168.0.100:7000', ), 'tcp_nodelay' => true, // set SOL_TCP,NO_DELAY=1 appropriately, thus disabling the TCP Nagle algorithm. 设置SOL_TCP,NO_DELAY=1,从而禁用TCP Nagle算法 ); // create the context... $context = stream_context_create($opts); // ...and use it to fetch the data echo file_get_contents('http://www.example.com', false, $context);
PHP 72 新特性
https://www.php.net/manual/zh/migration72.new-features.php
https://www.php.net/manual/en/migration72.new-features.php
新的对象类型
这种新的对象类型, object, 引进了可用于逆变(contravariant)参数输入和协变(covariant)返回任何对象类型。
function test(object $obj) : object { return new SplQueue(); } test(new StdClass());
通过名称加载扩展
加载扩展时不再需要指定文件扩展名 (Unix下以.so为文件扩展名,在Windows下以 .dll 为文件扩展名) 。
比如:extension=mysqli 就可以了,而不用 extension=mysqli.so
允许重写抽象方法(Abstract method)
abstract class A { abstract function test(string $s); } abstract class B extends A { // overridden - still maintaining contravariance for parameters and covariance for return abstract function test($s) : int; }
使用Argon2算法生成密码散列
Argon2 已经被加入到密码散列(password hashing) API (这些函数以 password_ 开头), 以下是暴露出来的常量:
PASSWORD_ARGON2I
PASSWORD_ARGON2_DEFAULT_MEMORY_COST
PASSWORD_ARGON2_DEFAULT_TIME_COST
PASSWORD_ARGON2_DEFAULT_THREADS
新增 ext/PDO(PDO扩展) 字符串扩展类型
当你准备支持多语言字符集,PDO的字符串类型已经扩展支持国际化的字符集。以下是扩展的常量
PDO::PARAM_STR_NATL
PDO::PARAM_STR_CHAR
PDO::ATTR_DEFAULT_STR_PARAM
$db->quote('über', PDO::PARAM_STR | PDO::PARAM_STR_NATL); //这些常量通过 PDO::PARAM_STR 利用位运算OR进行计算
为 ext/PDO扩展新增额外的模拟调试信息
PDOStatement::debugDumpParams()方法已经更新,当发送SQL到数据库的时候,在一致性、行查询(包括替换绑定占位符)将会显示调试信息。这一特性已经加入到模拟调试中(在模拟准备打开时可用)。
ext/LDAP(LDAP扩展) 支持新的操作方式
LDAP 扩展已经新增了EXOP支持. 扩展暴露以下函数和常量:
- ldap_parse_exop()
- ldap_exop()
- ldap_exop_passwd()
- ldap_exop_whoami()
LDAP_EXOP_START_TLS
LDAP_EXOP_MODIFY_PASSWD
LDAP_EXOP_REFRESH
LDAP_EXOP_WHO_AM_I
LDAP_EXOP_TURN
ext/sockets(sockets扩展)添加了地址信息
sockets扩展现在具有查找地址信息的能力,且可以连接到这个地址,或者进行绑定和解析。为此添加了以下一些函数:
Parameter type widening
放宽参数类型限制:重写方法和接口实现的参数类型可以省略。不过这仍然是符合LSP,因为现在这种参数类型是逆变的。
interface A { public function Test(array $input); } class B implements A { public function Test($input){} // type omitted for $input }
允许使用逗号批量引入同一命名空间下的 trait 类
PHP 7中命名空间允许使用逗号进行分组引入。
use Foo\Bar\{
Foo,
Bar,
Baz,
};
其他特性
- Windows下也支持 proc_nice() 函数
- pack() 和 unpack() endian支持
- 增强EXIF、ZIP扩展
- SQLite3 allows writing BLOBs
- ...
因为平时基本不会接触,所以具体参考英文文档吧
PHP 73 新特性
https://www.php.net/manual/zh/migration73.new-features.php
https://www.php.net/manual/en/migration73.new-features.php
更加灵活的Heredoc和Nowdoc语法
文档字符串的结束标记后面不再需要紧跟分号(;)或换行。另外,结束标记可以缩进,在这种情况下,缩进将从doc字符串中的每一行中删除。(可以使用空格或tab缩进,但是doc字符串和结束标记必须使用相同的缩进方式,要么都使用空格,要么都是tab,否则报错)
<?php echo <<<'NOW' 123 456 789
NOW // 此处可以省略分号,因为紧跟PHP结束标记 ?> // Output: (注意缩进:因为结束标记缩进了,所以doc字符串的每一行都删除相同的缩进)
123
456
789
<?php $nowDoc = <<<'NOW' 123 456 789 NOW ; echo "ASD\n" . $nowDoc;
// Output:(注意缩进)
ASD
123
456
789
对称数组分解支持引用赋值
数组分解([])现在支持引用赋值,list() 也一样。
$d = ['I am A', ['bbb', 'I am C']]; [&$a, [$b, &$c]] = $d; // 变量$a, $c 是引用赋值 // [&$a, [$b, &$c]] = ['I am A', ['bbb', 'I am C']]; 引用错误,编译不通过
Instanceof运算符接受字面量(Liters)
instanceof 现在允许字面量作为第一个操作数,在这种情况下,结果总是 FALSE。
PS:什么是字面量?
Value代表具体值,Literals则代表如何表达这个值。譬如说,15这是一个值,这个值是唯一的,但表达的方式有很多种:例如用阿拉伯数字写出来:15,用中文写出来:十五,用英文表达:fifteen,用16进制:0xF。15是value,后面的种种都是literal。
class A { } // 7.3之前前两个 var_dump 会编译错误 var_dump(A::class instanceof A); // Output: false var_dump('A' instanceof A); // Output: false var_dump(new A instanceof A); // Output: true
// 除了增强了 instanceof 容错性,暂时是没发现其他好处
异常类 CompileError 代替某些编译错误
A new CompileError exception has been added, from which ParseError inherits. A small number of compilation errors will now throw a CompileError instead of generating a fatal error. Currently this only affects compilation errors that may be thrown by token_get_all() in TOKEN_PARSE
mode, but more errors may be converted in the future. 底层新增的一个 CompileError 异常类。少量编译错误的情况现在将引发CompileError,而不是抛出致命错误。目前,这只会影响在TOKEN_PARSE模式下
token_get_all(),将来可能会转换更多错误。
Trailing Commas are allowed in Calls
允许调用方法、函数时使用逗号尾随。 官方文档中有人给出了这样的示例
// "Trailing commas in function and method calls are now allowed" means function parameters 尾随逗号,是针对函数或方法的参数而言的 function my1() { echo "xxxxxx\n"; } function my2() { echo "yyyyyy\n"; } my1(),my2(); // PHP Parse error: syntax error my1(,); // PHP Parse error: syntax error my1(1,); my2(2,); // OK
Argon2id 支持
The --with-password-argon2[=dir] configure argument now provides support for both Argon2i and Argon2id hashes in the password_hash(), password_verify(), password_get_info(), and password_needs_rehash() functions. Passwords may be hashed and verified using the PASSWORD_ARGON2ID
constant. Support for both Argon2i and Argon2id in the password_*() functions now requires PHP be linked against libargon2 reference library ≥ 20161029. 大体就是新增了Argon2id哈希算法支持
FastCGI Process Manager(FPM)
添加了新选项以自定义FPM日志:
log_limit
此全局选项可用于设置日志行的日志限制,允许记录长度超过1024个字符的消息而不进行换行。它还修复了各种换行问题。
log_buffering
This global option allows an experimental logging without extra buffering. 此全局选项允许不借助其它缓冲的情况下进行experimental logging。
decorate_workers_output
This pool option allows to disable the output decoration for workers output when catch_workers_output is enabled.
BC Math 数学运算函数
bcscale() 现在也可以用作getter来检索当前使用的scale(之前只能设置不能检索,返回值是bool;现在既能设置又能检索,返回值是int)
bcscale(2) ; // 设置所有bc数学函数的默认小数点保留2位小数 echo bcscale(); // 获取所有bc数学函数的默认小数点保留位数 Output: 2
Lightweight Directory Access Protocol
Full support for LDAP Controls has been added to the LDAP querying functions and ldap_parse_result():
- A $serverctrls parameter to send controls to the server in ldap_add(), ldap_mod_replace(), ldap_mod_add(), ldap_mod_del(), ldap_rename(), ldap_compare(), ldap_delete(), ldap_modify_batch(), ldap_search(), ldap_list() and ldap_read() has been added.
- The out parameter $serverctrls to get controls from the server in ldap_parse_result() has been added.
- Support for
LDAP_OPT_SERVER_CONTROLS
andLDAP_OPT_CLIENT_CONTROLS
in ldap_get_option() and ldap_set_option() has been fixed.
Multibyte String Functions 多字节字符串函数
mbstring扩展库的一些函数得到增强,优化。
- 增加对 full case-mapping 和 full case-folding 的支持,与 simple case-mapping 不同,full case-mapping可能会更改字符串的长度。
mb_strtoupper("Straße"); // Produces STRAßE on PHP 7.2 // Produces STRASSE on PHP 7.3
MB_CASE_LOWER
(used by mb_strtolower())MB_CASE_UPPER
(used by mb_strtoupper())MB_CASE_TITLE
MB_CASE_FOLD
MB_CASE_LOWER_SIMPLE
MB_CASE_UPPER_SIMPLE
MB_CASE_TITLE_SIMPLE
MB_CASE_FOLD_SIMPLE
(used by case-insensitive operations)
- 不区分大小写的字符串操作,现在比较时使用 case-folding 而不是 case-mapping。这意味着现在有更多的字符将被当成是相同的(大小写不敏感)。
- 使用 MB_CASE_TITLE 进行 mb_convert_case() 时,会基于大小写和大小写可忽略的派生Unicode属性执行 title-case(标题大小写)转换。特别是,这还改进了引号和撇号的处理。
- The Multibyte String data tables have been updated for Unicode 11.
- 现支持正确处理大于2GB的字符串。
- 性能改进提升,最大的改进是大小写转换函数。
- mb_ereg_x*函数现在支持命名捕获。匹配函数,如:mb_ereg() 现在将使用组号和组名返回命名捕获,类似于PCRE:
mb_ereg('(?<word>\w+)', '国', $matches); // Output: [0 => "国", 1 => "国", "word" => "国"]; // 另外, 在字符串替换时 mb_ereg_replace() 现支持用 \k<> and \k'' 符号来引用命名捕获: mb_ereg_replace('\s*(?<word>\w+)\s*', "_\k<word>_\k'word'_", ' foo '); // Output: "_foo_foo_"
\k<> and \k'' can also be used for numbered references, which also works with group numbers greater than 9. 【\k<>和\k''也可用于编号引用,这也适用于组号大于9的情况?】
Readline
readline_info() 中添加了对 completion_append_character 和 completion_suppress_append 选项的支持。只有当PHP链接到libreadline(而不是libedit)时,这些选项才可用。
PHP 74 新特性
https://www.php.net/manual/zh/migration74.new-features.php
https://www.php.net/manual/en/migration74.new-features.php
类型化属性
类属性支持类型声明
class User { public int $id; // 限定该属性只能被赋予 int 类型的值 public string $name; // 限定该属性只能被赋予 string 类型的值 }
Arrow functions 箭头函数/短闭包
剪头函数提供了一种简捷语法,用于定义具有隐式按值范围绑定的函数。
$factor = 10; $nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]); // $nums = array(10, 20, 30, 40); /** 如果要通过引用返回值,可以使用以下语法: */ fn&($n) => $n
注意事项:
- 可以访问父作用域,不需要 use 关键字。
- $this 可以像普通的闭包一样使用。
- 短闭包只能包含一行,也就是 return 语句,但是不需要也不能有 return 关键字(隐式返回)。
返回类型变异(协方差)、参数类型逆变
class A {} class B extends A {} class Producer { public function covariance(): A {} public function contravariance(B $b) {} } class ChildProducer extends Producer { public function covariance(): B {} public function contravariance(A $a) {} }
Null 合并运算符
$data['date'] = $data['date'] ?? new DateTime(); $data['date'] ??= new DateTime(); // PHP74中支持更简洁的写法
数组内展开运算符
$arrayA = [1, 2, 3]; $arrayB = [4, 5]; $result = [0, ...$arrayA, ...$arrayB, 6 ,7]; // 变量值:$result = [0, 1, 2, 3, 4, 5, 6, 7]
注意:这仅适用于“数字下标”的数组。
数字字面量分隔符
数字字面量在两个数字之间使用下划线"_"分割。
6.674_083e-11; // float 299_792_458; // decimal 0xCAFE_F00D; // hexadecimal 0b0101_1111; // binary
弱引用
弱引用允许程序员保留对某个对象的引用,但该引用不会阻止对象被销毁。
允许异常来至 __toString() 方法
现在允许从 __toString() 中抛出异常,以前这会导致致命错误,字符串转换中现有的可恢复致命错误已转换为 Error 异常。
CURL
如果扩展是针对libcurl>=7.56.0构建的,那么除了纯文件名之外,CURLFile现在还支持流包装器。
Filter
变量过滤器 FILTER_VALIDATE_FLOAT 现在支持 min_range 和 max_range 选项, FILTER_VALIDATE_INT 也一样。【filter_var() - 可以使用特定的过滤器过滤一个变量,FILTER_VALIDATE_FLOAT只是其中一个过滤器。】
// for filters that accept options, use this format $options = array( 'options' => array( 'default' => 3, // value to return if the filter fails // other options here 'min_range' => 0 ), 'flags' => FILTER_FLAG_ALLOW_OCTAL, ); $var = filter_var('0755', FILTER_VALIDATE_INT, $options); // for filter that only accept flags, you can pass them directly $var = filter_var('oops', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); // for filter that only accept flags, you can also pass as an array $var = filter_var('oops', FILTER_VALIDATE_BOOLEAN, array('flags' => FILTER_NULL_ON_FAILURE)); // callback validate filter function foo($value) { // Expected format: Surname, GivenNames if (strpos($value, ", ") === false) return false; list($surname, $givennames) = explode(", ", $value, 2); $empty = (empty($surname) || empty($givennames)); $notstrings = (!is_string($surname) || !is_string($givennames)); if ($empty || $notstrings) { return false; } else { return $value; } } $var = filter_var('Doe, Jane Sue', FILTER_CALLBACK, array('options' => 'foo'));
外部函数接口,简称 FFI
FFI是一个新的扩展,它提供了一种简单的方式来调用本机函数、访问本机变量以及创建/访问在C代码库中定义的数据结构,即允许从用户区调用 C 代码。这意味着可以用纯 PHP 编写PHP扩展。应该指出,这是一个复杂的话题。您仍然需要 C 知识才能正确使用此功能
GD库
添加了 IMG_FILTER_SCATTER 图像过滤器,以将一个 scatter filter 应用于图像。
哈希
使用 Castagnoli 多项式添加了 crc32c 哈希散列。此CRC32变体被用于存储系统,如iSCSI、SCTP、Btrfs和ext4。
多字节字符串
新增 mb_str_split() 函数,该函数提供了与 str_split() 一样的功能,但是操作的是 code points 而不是字节。
OPcache缓存预加载
预加载应该是该版本最值得一提的优化了,可以带来很大性能改进。简而言之:如果您今天使用的是框架,则必须在每次请求时加载和重新编译其文件。预加载允许服务器在启动时于内存中加载 PHP 文件,并使它们持久化用于所有后续请求(只要不停电)。
不过如果预加载文件的源文件发生变化,则必须重新启动服务器(该部分若有异议,请查看 RFC 详细介绍)
正则表达式(Perl兼容)
preg_replace_callback() 和 preg_replace_callback_array() 函数现在接受一个附加的flags参数,并支持 PREG_OFFSET_CAPTURE 和 PREG_UNMATCHED_AS_NULL 标志。这会影响传递给回调函数的匹配数组的格式。
PDO扩展
现在可以将用户名和密码指定为mysql、mssql、sybase、dblib、firebird和oci驱动程序的PDO DSN的一部分,以前这只受pgsql驱动程序支持。如果在构造函数和DSN中都指定了用户名/密码,则构造函数优先。
现在可以在SQL查询中转义问号,以避免它们被解释为参数占位符,写作 ?? 。例如使用PostgreSQL JSON 键 exists(?) 操作符。
- PDOStatement::getColumnMeta() 现在是可用支持的。
- PDOStatement::getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT) 允许检查语句是否是只读的,即它是否没有修改数据库。
- PDO::setAttribute(PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES, true) 允许在 PDO::errorInfo() 和 PDOStatement::errorInfo() 中使用SQLite3扩展结果代码。
- 添加了 SQLite3::lastExtendedErrorCode() 以获取最后一个扩展的结果代码.
- 添加了 SQLite3::enableExtendedResultCodes($enable=true),这将使 SQLite3::lastErrorCode() 返回扩展的结果代码。
strip_tags() 函数增强
strip_tags() 现在也支持 strip_tags($str, ['a', 'p']) 写法,等效于原来的写法 strip_tags($str, '<a><p>') 。
自定义对象序列化
RFC 增加了两个新的魔术方法:__serialize 和 __unserialize 。这些方法和 __sleep 以及 __wakeup 的不同之处已经在 RFC 中进行了讨论,主要是解决 __sleep, __wakeup 和 Serializable 带来的一些问题,如:__sleep只能用于从序列化中排除属性,但如果序列化后类的表示形式与内存中的形式有很大不同,使用起来则很麻烦。
// Returns array containing all the necessary state of the object. public function __serialize(): array; // Restores the object state from the given data array. public function __unserialize(array $data): void;
新的序列化机制将取代 Serializable 接口,后者将在将来被弃用。
不带参数的数组合并函数
array_merge() and array_merge_recursive() 现在可以不带任何参数进行调用,在这种情况下,它们将返回一个空数组。这与展开运算符(spread operator)结合使用非常有用,例如array_merge(…$arrays)。
proc_open() 函数
现在 proc_open() 的第一个参数接受一个数组而不是一个字符串。在这种情况下,进程将被直接打开(不经过shell),且PHP将负责任何必要的参数转义。
proc_open(['php', '-r', 'echo "Hello World\n";'], $descriptors, $pipes);
支持 重定向 和 null 描述符
// Like 2>&1 on the shell proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['redirect', 1]], $pipes); // Like 2>/dev/null or 2>nul on the shell proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['null']], $pipes);
argon2i(d) without libargon
当PHP在没有 libargon 的情况下构建时,password_hash() 现已有了来至 sodium 扩展的 argon2i 和 argon2id 实现。
password_hash() now has the argon2i and argon2id implementations from the sodium extension when PHP is built without libargon.
PS:PHP8 最引人注目的应该是引入了JIT(Just In Time), 但是从各种文档资料显示:要真正尽可能的达到“变编译边执行”的效果,需要开发者不断的尝试测试。
参考:
https://51shenyun.cn/php74/ PHP7.4新特性,OPcache将支持预加载
https://www.php.cn/topic/php7/437161.html PHP 7.4中的预加载(Opcache Preloading)