【翻译】PHP7——新特性

最后更新于:2022-04-01 09:56:07

原文地址: [http://php.net/manual/zh/migration70.new-features.php](http://php.net/manual/zh/migration70.new-features.php) ### 新特性 ### 标量类型声明 标量类型声明 有两种模式: 强制 (默认) 和 严格模式。 现在可以使用下列类型参数(无论用强制模式还是严格模式): 字符串(string), 整数 (int), 浮点数 (float), 以及布尔值 (bool)。它们扩充了PHP5中引入的其他类型:类名,接口,数组和 回调类型 ~~~ <?php // Coercive mode function sumOfInts(int ...$ints) { return array_sum($ints); } var_dump(sumOfInts(2, '3', 4.1)); ~~~ 以上例程会输出: ~~~ int(9) ~~~ 要使用严格模式,一个 declare 声明指令必须放在文件的顶部。这意味着严格声明标量是基于文件可配的。 这个指令不仅影响参数的类型声明,也影响到函数的返回值声明(参见 返回值类型声明, 内置的PHP函数以及扩展中加载的PHP函数) 完整的标量类型声明文档和示例参见类型声明章节。 ### 返回值类型声明 PHP 7 增加了对返回类型声明的支持。 类似于参数类型声明,返回类型声明指明了函数返回值的类型。可用的类型与参数声明中可用的类型相同。 ~~~ <?php function arraysSum(array ...$arrays): array { return array_map(function(array $array): int { return array_sum($array); }, $arrays); } print_r(arraysSum([1,2,3], [4,5,6], [7,8,9])); ~~~ 以上例程会输出: ~~~ Array ( [0] => 6 [1] => 15 [2] => 24 ) ~~~ 完整的标量类型声明文档和示例可参见 返回值类型声明. ### null合并运算符 由于日常使用中存在大量同时使用三元表达式和 isset()的情况, 我们添加了null合并运算符 (??) 这个语法糖。如果变量存在且值不为NULL, 它就会返回自身的值,否则返回它的第二个操作数。 ~~~ <?php // Fetches the value of $_GET['user'] and returns 'nobody' // if it does not exist. $username = $_GET['user'] ?? 'nobody'; // This is equivalent to: $username = isset($_GET['user']) ? $_GET['user'] : 'nobody'; // Coalesces can be chained: this will return the first // defined value out of $_GET['user'], $_POST['user'], and // 'nobody'. $username = $_GET['user'] ?? $_POST['user'] ?? 'nobody'; ?> ~~~ ### 太空船操作符(组合比较符) 太空船操作符用于比较两个表达式。当a大于、等于或小于b时它分别返回-1、0或1。 比较的原则是沿用 PHP 的常规比较规则进行的。 ~~~ <?php // Integers echo 1 <=> 1; // 0 echo 1 <=> 2; // -1 echo 2 <=> 1; // 1 // Floats echo 1.5 <=> 1.5; // 0 echo 1.5 <=> 2.5; // -1 echo 2.5 <=> 1.5; // 1 // Strings echo "a" <=> "a"; // 0 echo "a" <=> "b"; // -1 echo "b" <=> "a"; // 1 ?> ~~~ ### 通过 define() 定义常量数组 Array 类型的常量现在可以通过 definedefine() 来定义。在 PHP5.6 中仅能通过 const 定义。 ~~~ <?php define('ANIMALS', [ 'dog', 'cat', 'bird' ]); echo ANIMALS[1]; // outputs "cat" ?> ~~~ ### 匿名类 现在支持通过new class 来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义 ~~~ <?php interface Logger { public function log(string $msg); } class Application { private $logger; public function getLogger(): Logger { return $this->logger; } public function setLogger(Logger $logger) { $this->logger = $logger; } } $app = new Application; $app->setLogger(new class implements Logger { public function log(string $msg) { echo $msg; } }); var_dump($app->getLogger()); ?> ~~~ 以上例程会输出: ~~~ object(class@anonymous)#2 (0) { } ~~~ 详细文档可以参考 匿名类. ### Unicode codepoint 转译语法 这接受一个以16进制形式的 Unicode codepoint,并打印出一个双引号或heredoc包围的 UTF-8 编码格式的字符串。 可以接受任何有效的 codepoint,并且开头的 0 是可以省略的。 ~~~ echo "\u{aa}"; echo "\u{0000aa}"; echo "\u{9999}"; ~~~ 以上例程会输出: ~~~ ª ª (same as before but with optional leading 0's) 香 ~~~ ### Closure::call() Closure::call() 现在有着更好的性能,简短干练的暂时绑定一个方法到对象上闭包并调用它。 ~~~ <?php class A {private $x = 1;} // Pre PHP 7 code $getXCB = function() {return $this->x;}; $getX = $getXCB->bindTo(new A, 'A'); // intermediate closure echo $getX(); // PHP 7+ code $getX = function() {return $this->x;}; echo $getX->call(new A); ~~~ 以上例程会输出: ~~~ 1 1 ~~~ ### 为unserialize()提供过滤 这个特性旨在提供更安全的方式解包不可靠的数据。它通过白名单的方式来防止潜在的代码注入。 ~~~ <?php // converts all objects into __PHP_Incomplete_Class object $data = unserialize($foo, ["allowed_classes" => false]); // converts all objects into __PHP_Incomplete_Class object except those of MyClass and MyClass2 $data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]); // default behaviour (same as omitting the second argument) that accepts all classes $data = unserialize($foo, ["allowed_classes" => true]); ~~~ ### IntlChar 新增加的 IntlChar 类旨在暴露出更多的 ICU 功能。这个类自身定义了许多静态方法用于操作多字符集的 unicode 字符。 ~~~ <?php printf('%x', IntlChar::CODEPOINT_MAX); echo IntlChar::charName('@'); var_dump(IntlChar::ispunct('!')); ~~~ 以上例程会输出: ~~~ 10ffff COMMERCIAL AT bool(true) ~~~ 若要使用此类,请先安装Intl扩展 ### 预期 预期是向后兼用并增强之前的 assert() 的方法。 它使得在生产环境中启用断言为零成本,并且提供当断言失败时抛出特定异常的能力。 老版本的API出于兼容目的将继续被维护,assert()现在是一个语言结构,它允许第一个参数是一个表达式,而不仅仅是一个待计算的 string或一个待测试的boolean。 ~~~ <?php ini_set('assert.exception', 1); class CustomError extends AssertionError {} assert(false, new CustomError('Some error message')); ?> ~~~ 以上例程会输出: ~~~ Fatal error: Uncaught CustomError: Some error message ~~~ 关于这个特性的完整说明,包括如何在开发和生产环境中配置它,可以在assert()的 expectations section章节找到。 ### Group use declarations 从同一 namespace 导入的类、函数和常量现在可以通过单个 use 语句 一次性导入了。 ~~~ <?php // Pre PHP 7 code 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+ code 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}; ?> ~~~ ### Generator Return Expressions 此功能是建立在引入PHP5.5发电机的功能。它能够为要在发电机内使用,以便为最终的表达式返回return语句(返回引用是不允许的)。该值可以使用新的发电机:: getReturn()方法,该方法只能使用一次发电机已完成收益值是牵强。 ~~~ <?php $gen = (function() { yield 1; yield 2; return 3; })(); foreach ($gen as $val) { echo $val, PHP_EOL; } echo $gen->getReturn(), PHP_EOL; ~~~ 以上例程会输出: ~~~ 1 2 3 ~~~ 能够从发电机明确地返回一个最终值是有一个方便的能力。这是因为它使供到由发电机被返回(从或许某种形式的协程计算),可以通过执行发生器客户代码进行具体处理的最终值。这比迫使客户端代码首先检查最终值是否已经产生了,然后如果是这样,专门负责处理该值简单。 ### Generator delegation 发电机现在可以委托给另一发生器,自动位移对象或数组,而无需使用来自结构屈服编写样板在最外面的发电机。 ~~~ <?php function gen() { yield 1; yield 2; yield from gen2(); } function gen2() { yield 3; yield 4; } foreach (gen() as $val) { echo $val, PHP_EOL; } ?> ~~~ 以上例程会输出: ~~~ 1 2 3 4 ~~~ ### Integer division with intdiv() 新intdiv()函数执行的操作数的整数除法并返回。 ~~~ <?php var_dump(intdiv(10, 3)); ?> ~~~ 以上例程会输出: ~~~ int(3) ~~~ ### Session options 在session_start()现在接受的选项,覆盖在php.ini中通常设置会话配置指令的数组。 这些选项也得到了扩展,以支持session.lazy_write,这是在默认情况下并导致PHP只覆盖任何会话文件,如果会话数据已经改变,read_and_close,这是一个只能传递给在session_start()的选项,以表明会话数据应该读,然后会议应立即关闭不变。 例如,要session.cache_limiter设置为私有,并立即阅读后关闭会话: ~~~ <?php session_start([ 'cache_limiter' => 'private', 'read_and_close' => true, ]); ?> ~~~ ### preg_replace_callback_array() 新preg_replace_callback_array()函数使代码编写更干净使用preg_replace_callback()函数时。在此之前PHP7,这需要每个正则表达式执行回调需要回调函数被污染,有很多分支。 现在,回调可以注册使用一个关联数组,其中最关键的是一个正则表达式的值是一个回调的每个正则表达式。 ### CSPRNG Functions 两个新的功能已被添加到生成加密安全整数和字符串的跨平台的方式:random_bytes()和random_int()。 ### list() can always unpack objects implementing ArrayAccess 此前,列表()是不能保证与实施了ArrayAccess对象的正常运行。这已得到修复。
';