写点什么

PHP 8:数组、变量、操作符、异常处理

  • 2023-06-11
    北京
  • 本文字数:10145 字

    阅读完需:约 33 分钟

PHP 8:数组、变量、操作符、异常处理

本文属于专题文章《深入浅出 PHP 8》


根据w3tech的数据,PHP 仍是互联网上使用最为广泛的脚本语言之一,77.3%的网站在服务器端均使用该编程语言。PHP 8 为我们带来了许多新功能与优化,具体将在本系列文章中分析。


本篇介绍几个新特性以及与数组、变量、运算符、异常处理和 trait 等有关的改进。

数组与字符串

弃用 false 值的 Autovivification

Autovivification是指当引用数组中未定义的元素时自动创建新数组,例如:


<?php$arr['a'][1] = 'a';var_dump($arr);
复制代码


新数组$arr是自动创建出来的,它在被引用之前并不存在。输出如下:


array(1) { ["a"]=> array(1) { [1]=> string(1) "a" } }
复制代码


Autovivification 允许开发人员引用结构化变量(如数组)及其子元素,而无需首先显式地创建该结构化变量。


PHP 8.0 支持未定义变量、空值和false值的 Autovivification 。下面的脚本演示了null值的 Autovivification:


<?php$arr   = null;$arr[] = 1;var_dump($arr);
复制代码


输出如下:


array(1) { [0]=> int(1) }
复制代码


下面的脚本演示了未定义变量的 Autovivification:


<?php$arr[]                     = 'undefined value';$arr['variableNotExist'][] = 1;
var_dump($arr);
复制代码


上述脚本输出如下:


array(2) { [0]=> string(15) "undefined value" ["variableNotExist"]=> array(1) { [0]=> int(1) } }
复制代码


PHP 8.0 甚至允许false的 Autovivification。不过,PHP 8.0 不支持标量值的 Autovivification,如下面的脚本所示:


<?php$arr   = 1;$arr[] = 1;var_dump($arr);
复制代码


上述脚本输出如下:


Uncaught Error: 不能将标量值作为数组来使用在 PHP 8.1 中,Autovivification 只支持未定义的变量和null 值,已放弃支持false值的 Autovivification。想证明这一点,可以运行以下脚本:


<?php $arr = false;$arr[] = 1;
复制代码


上述脚本输出如下:


Deprecated: 从 false 到数组的自动转换已弃用

字符串键数组解包

解包的使用语境是逐项列出数组元素,或使用解包运算符...取出数组元素。PHP 8.0 不允许对数组中的字符串键进行解包,就像不允许对函数的参数进行解包一样。PHP 8.1 通过引入命名参数提供了函数参数解包支持;命名参数可以在参数解包之后使用,条件是命名参数不能覆盖已解包的参数。“PHP 8:函数和方法的新特性”一文中有一个演示函数命名参数解包的示例。


此外,PHP 8.1 还允许使用运算符将字符串键解包到数组中,如下所示:


<?php
$array1 = ["one" => 1];$array2 = ["two" => 2];$array1 = ["one" => "one"];$array2 = ["two" => "two"];$array = ["one" => 0, "two" => 10, ...$array1, ...$array2];var_dump($array);
复制代码


运算符解包$array1array2,前一个数组的键被后一个数组的键所覆盖。输出结果如下:


array(2) { ["one"]=> string(3) "one" ["two"]=> string(3) "two" }array_merge()函数用于在后台解包数组,因此,解包前面示例中的两个数组可以调用array_merge($array1,$array2)


新特性仅影响字符串键,而整数键将重新编号;原来的整数键不会保留。使用整数键的示例如下:


<?php
$array1 = [1 => 1];$array2 = [2 => 2];$array1 = [1 => "one"];$array2 = [2 => "two"];$array = [1 => 0, 2 => 10, ...$array1, ...$array2];var_dump($array);
复制代码


下面给出了解包字符串键数组的另一个示例,其中引号括起来的整数键实际上会被当作整数键。包含整数的字符串键会被强制转换为整数类型,例如:


<?php  
$array1 = ["1" => 1];$array2 = ["2" => 2];$array1 = ["1" => "one"];$array2 = ["2" => "two"];$array = ["one" => 0, "two" => 10, ...$array1, ...$array2];var_dump($array);
复制代码


输出如下:


array(4) { ["one"]=> int(0) ["two"]=> int(10) [0]=> string(3) "one" [1]=> string(3) "two" }
复制代码

确定数组是否是列表的新函数

数组类型支持字符串键和整数键。有时候,我们需要知道数组键的实际编号是否为0…count($array)-1。在这种情况下,我们将数组称为列表。新增函数array_is_list(array $array): bool就是为了完成这项工作。如果数组是一个列表,则该函数会返回一个booltrue,如果不是,则返回false。下面的例子演示了这个新函数:


<?php  $x = [1 => 'a', 0 => 'b', 2=>'c'];
$y = [0 => 'a', 1 => 'b', 2=>'c'];var_export(array_is_list($x)); var_export(array_is_list($y));
复制代码


输出如下:


falsetrue

数组排序变得稳定

在 PHP 7 中,数组的排序操作是不稳定的。“不稳定”意味着在连续排序中,不能保证“相等”的元素顺序一致。PHP 8.0 中排序变得稳定。如果输入数组中有多个元素相等,则它们在排序完成后总是邻接。换句话说,相等的元素会保持它们在原数组中的顺序。当按照复杂数据的特定属性进行排序时,这一特性特别有用。在这种情况下,如果排序不稳定,则可能会导致输出不一致。下面的脚本演示了稳定排序:


<?php $array = [    'd' => 'c',    'c' => 'c',    'b' => 'a',    'a' => 'a',]; asort($array);
foreach ($array as $key => $val) { echo "array[" . $key . "] = " . $val . "\n"; }
复制代码


在稳定排序中,结果总是:


array[b] = a array[a] = a array[d] = c array[c] = c
复制代码

弃用 ${}字符串插值

在双引号(")中的字符串里嵌入变量可以有多种形式。PHP 8.2 弃用了两种字符串插值形式:${var}${expr}${var}形式与其他两种形式("$var")("{$var}")语法上存在重叠,并且功能不如其他形式强大。${expr}(string) ${expr}等价,很少使用。


下面的例子展示了允许的字符串插值形式,以及不允许的形式${var}${expr}


<?php $str = 'hello'; var_dump("$str");var_dump("{$str}");var_dump("${str}");
var_dump("${str}"); var_dump("${(str)}");
复制代码


上述脚本输出如下:


Deprecated: 字符串插值形式 {var} 已弃用,请使用{var} 代替 in /home/deepakvohra/php-src/scripts/php-info.php on line 8Deprecated: 字符串插值形式 {var}已弃用,请使用{var} 代替 in /home/deepakvohra/php-src/scripts/php-info.php on line 10Deprecated: 字符串插值形式 {expr} (variable variables)已弃用 ,请使用 {{expr}} 代替 in /home/deepakvohra/php-src/scripts/php-info.php on line 12string(5) "hello" string(5) "hello" string(5) "hello" string(5) "hello"Fatal error: Uncaught Error: 未定义常量 "str"

异常处理

PHP 8.0 引入了非捕获catch。以前,每个catch语句都必须为被捕获的异常声明一个变量。例如,下面的脚本在catch语句中声明了Exception类型的变量$exc


<?php
function sortArray(array $arrayToSort){ try { if (count($arrayToSort) === 0) { throw new Exception("Array is empty; please provide a non-empty array"); } } catch (Exception $exc) { echo $exc; }}
$arrayToSort = array();
复制代码


执行上述脚本会输出下面这条异常信息:


Exception: 数组为空,请提供一个非空数组虽然前面的示例使用了$exc变量,但也不是一定要使用异常变量。对于非捕获catch,异常变量是可选的;不声明异常变量,因此也就不能使用,如下所示:


<?php
function sortArray(array $arrayToSort){ try { if (count($arrayToSort) === 0) { throw new Exception("Array is empty; please provide a non-empty array"); } } catch (Exception) { }}
复制代码


多捕获catch语句也可以是非捕获catch,如下所示:


<?php
class Exception1 extends Exception{}
class Exception2 extends Exception{}
class A{ public function fn1() { try { throw new Exception1(); } catch (Exception1 | Exception2) { } }}
复制代码

抛出异常

throw语句以前不能在表达式中使用。PHP 8.0 增加了在表达式中使用throw的支持。例如,在以下脚本中,match 表达式在default中使用了throw表达式。


<?php
$vector = new \Ds\Vector();
$vector->push('a');
try {match ('set') { 'push' => $vector->push('b'), 'pop' => $vector->pop(), default => throw new Exception()}; }catch (Exception $exc) { echo $exc;}print_r($vector);
复制代码


输出如下:


Exception in C:\php-8.1.9-nts-Win32-vs16-x64\scripts\sample.php:11 Stack trace: #0 {main}Ds\Vector Object ( [0] => a )
复制代码


下面的例子将throw与空值合并运算符(??)一起使用:


<?php $name = $_GET['name'] ?? throw new Exception("请提供请求参数'name'");
echo "Hello " . htmlspecialchars($name)."<br>";
复制代码


输出如下:


Uncaught Exception: 请提供请求参数'name'在下面的例子中,throw 和三元运算符(?)一起使用:


<?php
try { function fn1(bool $param1) { $value = $param1 ? true: throw new InvalidArgumentException(); } fn1(true); fn1(false);}catch (Exception $exc) { echo $exc;}
复制代码


输出如下:


InvalidArgumentException in C:\php-8.1.9-nts-Win32-vs16-x64\scripts\sample.php:5 Stack trace: #0 C:\php-8.1.9-nts-Win32-vs16-x64\scripts\sample.php(9): fn1(false) #1 {main}
复制代码

变量

整型字面量的显式八进制表示法

字面量八进制表示法可能产生误导性结果,例如12 === 012的计算结果为false。PHP 8.1 增加了对整型字面量显式八进制表示法0o/0O 的支持,类似于十六进制的0x/0x表示法和二进制的0b/0b表示法。下面的脚本演示了显式八进制表示法:


<?php   var_export(0o12 === 10);   var_export(0o26 === 22);
var_export(0O12 === 10); var_export(0O26 === 22);


var_export(012 === 0o12); var_export(012 === 0O12);
复制代码


输出如下:


truetruetruetruetruetrue
复制代码

限制 $GLOBALS 的使用

通过$GLOBALS变量可以直接访问内部符号表,新版本对它的使用增加了一些限制。从 PHP 8.1 开始,$GLOBALS只能使用$GLOBALS[$name] = $value语法来修改。为了证明这一点,可以运行下面这个直接访问$GLOBALS的脚本:


<?php$x=1;  $GLOBALS = 1;$GLOBALS += 1;$GLOBALS =& $x;$x =& $GLOBALS;unset($GLOBALS);
复制代码


上述脚本会导致以下错误信息:


GLOBALS[value 语法来修改下面这种使用GLOBALS 的方法就没问题:


<?php$GLOBALS['a'] = 1;$GLOBALS['a']--;var_dump($GLOBALS['a']);
复制代码


输出如下:


int(0)
复制代码

将命名空间名称视为单个标记

为了使保留关键字可以出现在命名空间名称中,PHP 8.0 将把命名空间名称视为单个标记。这降低了引入新的保留字时,因为现有命名空间名称已使用该保留字而导致向后不兼容的可能性。


为了说明这一点,下面的脚本在命名空间名称中使用了保留字fn。该脚本还使用了ReflectionClass来输出类的属性,比如它是否是一个命名空间、类名、命名空间和类方法:


<?phpnamespace  do\while\fn\iter;
function fn1(){}class C{ static function fn2() { }}
$class = new \ReflectionClass('do\while\fn\iter\C');
var_dump($class->inNamespace());var_dump($class->getName());var_dump($class->getNamespaceName());
$methods = $class->getMethods();var_dump($methods);
复制代码


输出如下:


bool(true) string(18) "do\while\fn\iter\C" string(16) "do\while\fn\iter" array(1) { [0]=> object(ReflectionMethod)#2 (2) { ["name"]=> string(3) "fn2" ["class"]=> string(18) "do\while\fn\iter\C" } }
复制代码

运算符

PHP 8 增加了许多与新运算符相关的特性。

非严格字符串数字比较变得更加有用

在 PHP 8.0 之前,非严格字符串数字比较都是假设字符串实际上是一个数字,并将字符串转换为数字后进行数字比较。PHP 8.0 会在转换类型并进行数字比较之前确保字符串是一个数字。否则,它会将数字转换为字符串,并进行字符串比较。新特性不适用于严格比较运算符===!==。这些运算符要求两个操作数具有相同的类型,并且不执行隐式类型转换。受影响的只有非严格比较运算符==!=>>=<<=。下面的脚本演示了新的字符串数字比较:


<?php var_dump(1 == "001");         var_dump(1 == "1.0");           var_dump(1.0 == "+1.0E0");  
var_dump(1 == "1 ");
var_dump(1 == " 1");


var_dump(1 == " 1 "); var_dump("one" == "1");
var_dump("one" != "1");
复制代码


输出如下:


bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(false) bool(true)

空值安全运算符

你是不是经常调用方法或获取表达式结果的属性并假设结果非空?由于结果可能为空,所以最好首先确保它不是空的。你可以显式地使用if(result!=null)进行比较,但它可能涉及层次化的多重比较。下面的脚本使用传统的if比较,对整数值的加法进行空值安全的比较:


<?php class Sum{    public int $i;
function __construct() { $this->i = 0; } function addA(Sum $sum,int $a):?Sum { $sum->i= $a+$sum->i; return $sum; } function addB(Sum $sum,int $b):?Sum { $sum->i= $b+$sum->i; return $sum; } function addC(Sum $sum,int $c):?Sum { $sum->i= $c+$sum->i; return $sum; }
function getSum(Sum $sum):int { return $sum->i; }
}


$a = new Sum();
if ($a->addA($a,1) !== null) { if ($a->addB($a,2) !== null) { if ($a->addC($a,3) !== null) { echo $a->getSum($a); } }}
复制代码


上述脚本的结果是6


新运算符?->可用于链接调用以进行空值安全比较,当运算符的左操作数计算结果为null时,它将停止所有后续的比较。对于上述加法操作,以下脚本演示了链接操作数,使用新运算符?-> 进行空值安全比较。


echo $a->addA($a,1)?->addB($a,2)?->addC($a,3)?->getSum($a);
复制代码

与语言环境无关的浮点数字符串转换

在 PHP 8.0 之前,浮点数到字符串类型的转换依赖于语言环境,也就是说,小数分隔符会因语言环境而异。这可能会导致一些不一致,例如将字符串解释为格式错误,或将字符串解释为数值。开发人员非常需要一致的浮点数字符串表示,而 PHP 8.0 正好提供了这一点。下面的脚本演示了与本地语言环境无关的浮点数字符串转换。


<?php setlocale(LC_ALL, "de_DE");$f = 1.23; echo (string) $f;      echo strval($f);
复制代码


输出结果如下:


1.231.23
复制代码

对算术/位运算符进行更严格的类型检查

算术/位运算符+-*/**%<<>>&|^~++-只能应用于支持这些运算符的操作数。这些运算符不能用于数组、资源或非重载对象操作数。PHP 8.0 会进行严格的类型检查,如果操作数与算术/位运算符不兼容,则抛出TypeError。为了演示这一点,下面的脚本对数组使用了减法运算符(-):


<?php  $arrayToSort = array(3, 1, 0, 2); var_dump($arrayToSort - [1]);
复制代码


上述脚本会导致以下错误:


Uncaught TypeError: 不支持的操作数类型: array - array 
复制代码

在常量表达式中使用->/?- >运算符获取枚举属性

枚举对象不允许出现在常量表达式中,如数组键,这样你就无法在常量表达式中获取枚举属性的名称和值。为了演示这一点,请使用 8.1 版本运行以下脚本:


<?php
enum Sort: string { case ASC = 'ASC'; const SortType = [self::ASC->name => self::ASC->value];}
复制代码


上述脚本会导致如下错误信息:


常量表达式包含无效操作 PHP 8.2 允许在常量表达式中使用-> ?->运算符获取枚举属性,如下所示:


<?php
enum Sort: string { case ASC = 'ASC'; const SortType = [self::ASC->name => self::ASC->value];}function get(){ static $g = Sort::ASC->value;}
#[Attr(Sort::ASC->name)]class SortClass{}
function set($s = Sort::ASC->value,){}
class SortClass2{ public string $n = Sort::ASC->name;}// The rhs of -> allows other constant expressionsconst DESC = 'DESC';class SortClass3{ const C = Sort::ASC->{DESC};}
复制代码

Trait

抽象 trait 方法验证

PHP 8.0 会在组合/使用类中验证抽象 trait 方法,以确保它们的签名匹配。实现方法必须与 trait 方法兼容,这里的兼容被定义为签名兼容:


  • 参数数量兼容:函数参数的数量必须相同

  • 逆变参数类型兼容

  • 协变返回类型兼容另外,静态方法必须保持静态。抽象 trait 方法可以是私有的。下面的脚本演示了抽象 trait 方法的一个准确实现:


<?php trait HelloTrait {    abstract private function hello(): string;     public function getMsgLength() {        return strlen($this->hello());    }} class A {    use HelloTrait;   private function hello(): string {return "Hello John"; }}
复制代码


为了演示不兼容的情况,将实现方法修改如下:


private function hello(): stdClass { }
复制代码


在这种情况下,会报以下错误信息:


A::hello(): stdClass的声明必须与HelloTrait::hello(): string兼容
复制代码


不能在类中将 trait 中的非静态方法变成静态。为了演示这一点,修改实现如下:


private static function hello(): string { }
复制代码


上述脚本会报以下错误信息:


无法在类A中将非静态方法HelloTrait::hello()变成静态
复制代码

弃用在 Trait 上调用静态元素的特性

PHP 8.1.0 放弃在 trait 上调用静态元素的支持,也就是说,不能直接在 trait 上调用静态方法或静态属性。只能通过使用 trait 的类访问 trait 的静态方法和属性。下面的脚本演示了这种情况:


<?php trait HelloTrait {
public static $a = 'static property in trait'; public static function hello(): string {return "Hello";} } class A { use HelloTrait; }
echo A::$a; echo A::hello();
echo HelloTrait::$a;echo HelloTrait::hello();
复制代码


输出如下:


Deprecated: 不能直接访问静态 trait 属性 HelloTrait::$a,只能通过使用该 trait 的类访问 Deprecated: 不能直接访问静态 trait 方法 HelloTrait::hello,只能通过使用该 trait 的类访问

Trait 中的常量

PHP 8.1 不允许在 trait 中使用不变量(也称为常量)。PHP 8.2 增加了对在 trait 中使用常量的支持。这些常量可以由 trait 的方法使用,也可以在组合类中使用。为了演示常量在 trait 中的用处,请看下面的示例。其中,组合类中声明了一个名为MAX_ARRAY_SIZE的常量:


<?php
trait SortTrait{ public function sortArray(array $arrayToSort): void { if (count($arrayToSort) > self::MAX_ARRAY_SIZE) { throw new \Exception("array size out of range"); } else { sort($arrayToSort); foreach ($arrayToSort as $key => $val) { echo "$key = $val "; } echo "<br/>"; } }}
class SortClass{ private const MAX_ARRAY_SIZE = 10; use SortTrait;}
$arrayToSort = ["B", "A", "f", "C", 1, "a", "F", "B", "b", "d"];$obj = new SortClass();$obj->sortArray($arrayToSort);
复制代码


运行上述脚本会生成以下输出:


0 = 1 1 = A 2 = B 3 = B 4 = C 5 = F 6 = a 7 = b 8 = d 9 = f 下面是同一脚本的 8.2 版本,在 trait 中声明了常量MAX_ARRAY_SIZE


<?php
trait SortTrait{ public const MAX_ARRAY_SIZE = 10;
public function sortArray(array $arrayToSort): void { if (count($arrayToSort) > self::MAX_ARRAY_SIZE) { throw new \Exception("array size out of range"); } else { sort($arrayToSort); foreach ($arrayToSort as $key => $val) { echo "$key = $val "; } echo "<br/>"; } }}
class SortClass{ use SortTrait;}
$arrayToSort = ["B", "A", "f", "C", 1, "a", "F", "B", "b", "d"];$obj = new SortClass();$obj->sortArray($arrayToSort);
复制代码


输出相同:


0 = 1 1 = A 2 = B 3 = B 4 = C 5 = F 6 = a 7 = b 8 = d 9 = f 再看一个例子。下面的脚本在 trait 中声明了 3 个常量,并在 trait 中使用了它们:


<?php
trait SortTrait{ public const SORT_TYPE_1 = "ASC"; public const SORT_TYPE_2 = "DESC"; public const SORT_TYPE_3 = "SHUFFLE";
public function getSortType(string $sortType): void { if (str_contains($sortType, self::SORT_TYPE_1)) { echo "Sort type is ASC"; } if (str_contains($sortType, self::SORT_TYPE_2)) { echo "Sort type is DESC"; } if (str_contains($sortType, self::SORT_TYPE_3)) { echo "Sort type is SHUFFLE"; } }}
class SortClass{ use SortTrait;}
$obj = new SortClass();
$obj->getSortType("ASCending");
复制代码


输出如下:


Sort type is ASCTrait 常量无法通过TRAIT_NAME::CONSTANT 语法直接访问,就像下面的脚本这样:


<?php
trait SortTrait{ public const SORT_TYPE_1 = "ASC"; public const SORT_TYPE_2 = "DESC"; public const SORT_TYPE_3 = "SHUFFLE";
public function getSortType(string $sortType): void { if (str_contains($sortType, SortTrait::SORT_TYPE_1)) { echo "Sort type is ASC"; } if (str_contains($sortType, self::SORT_TYPE_2)) { echo "Sort type is DESC"; } if (str_contains($sortType, self::SORT_TYPE_3)) { echo "Sort type is SHUFFLE"; } }}
class SortClass{ use SortTrait;}
$obj = new SortClass();
$obj->getSortType("ASCending");
复制代码


执行上述脚本会输出以下错误信息:


Uncaught Error: 不能直接访问 trait 常量 SortTrait::SORT_TYPE_1 使用$this就可以,如下所示:


if (str_contains($sortType, $this::SORT_TYPE_1)) {            echo 'Sort type is ASC';        }
复制代码


Trait 常量可以声明为 final 类常量。适用于 trait 属性的兼容性限制也适用于它的常量。


枚举可以使用包含常量的 trait,和直接在枚举中定义它们一样,如下所示:


<?php
trait SortTrait{ private const SortType = "ASC";}
enum Enum1: int{ use SortTrait;
case CaseA = self::SortType;}
复制代码

逐步淘汰 Serializable

PHP 7.4 引入了自定义序列化机制,借助两个新的魔法方法:__serialize(): array__unserialize(array $data): void__serialize()方法返回一个包含对象所有必要状态的数组,__unserialize()方法从给定的数据数组中恢复对象状态。新的自定义序列化机制旨在逐步淘汰Serializable接口。如果一个非抽象类实现了Serializable,但没有实现__serialize()__unserialize(), PHP 8.1 就会生成一条弃用警告。这样的一个类被称为“only Serializable”。为了演示这一点,可以运行下面的脚本:


<?php class A implements Serializable {}
复制代码


执行上述脚本会显示以下弃用信息:


Deprecated: A 实现了 Serializable 接口,该接口已弃用。如果需要支持旧的 PHP 版本,请实现__serialize()和__unserialize()Fatal error: 类 A 包含 2 个抽象方法,因此必须声明为抽象的,或者实现其余的方法 (Serializable::serialize, Serializable::unserialize)

弃用动态属性

动态类属性是在声明之前被引用的属性。动态属性是自动创建的。PHP 8.2 已弃用动态属性。这主要是为了避免这样一种情况:用户无意创建新属性,但却因为输入了错误的属性名称而创建了新属性。为了演示这一点,在 PHP 8.2 中运行下面的脚本创建一个动态属性:


<?php
class A{ public $name;}
$a = new A();
// 给已声明的属性User::$name赋值$a->name = "John";
$a->firstname = "John";
复制代码


执行上述脚本会输出以下弃用信息:


Deprecated: 已弃用创建动态属性 A::$firstname 如果你仍然希望动态属性实现魔术方法__get/__set,或使用新属性#[AllowDynamicProperties],则预打包类stdClass已经用#[AllowDynamicProperties]属性标记。

弃用向内置函数的非可空参数传递 null 值的特性

当强类型模式设置为(strict_types=1)时,用户定义函数不接受向非空参数传递null值。在 PHP 8.1 中,即使是内置函数也不会接受向非空参数传递null值,如下所示,它会生成弃用通知:


<?php$var=null; strlen($var);
复制代码


输出如下:


Deprecated: strlen(): 向 string 类型的参数 #1 ($string)传递 null 的特性已弃用在 PHP 9.0 中,TypeError弃用通知将被替换为错误。


在本文中,我们讨论了 PHP 8 中与数组、变量、运算符和异常处理相关的新特性。我们还讨论了一些与 trait、类和函数相关的特性。


原文链接:

https://www.infoq.com/articles/php8-arrays-variables-operators/


相关阅读:

PHP 8:注解、match 表达式及其他改进

PHP 8:类和枚举

PHP 8:函数和方法

2023-06-11 08:004687

评论

发布
暂无评论
发现更多内容

互联网流量编排方案

穿过生命散发芬芳

7月月更 流量编排

Go 并发编程基础:什么是上下文

宇宙之一粟

并发编程 Go 语言 7月月更

LeetCode-83. 删除排序链表中的重复元素(java)

bug菌

Leet Code 7月月更

沉淀2年的 Jira 自动化经验分享

跟YY哥学Jira

RPA 自动化 Jira

Java 虚拟机的概念是怎么来的

HoneyMoose

百变小精灵,CRMEB Java 单商户系统也要当!

CRMEB

OSI七层模型有哪七层?每一层分别有啥作用,这篇文章讲的明明白白!

wljslmz

OSI七层协议 网络技术 7月月更

JavaScript 中如何取消请求

掘金安东尼

JavaScript 前端 7月月更

项目升级遇到的坑

技术小生

7月月更

教你学c++算法题中最简单的二分,我不允许还有人不会!!!!

KEY.L

7月月更

【K8s入门必看】第二篇 —— 快速部署集群指南

Albert Edison

Docker Kubernetes 容器 云原生 7月月更

python小知识-python格式化

AIWeker

Python python小知识 7月月更

zookeeper-curator开源框架介绍

zarmnosaj

7月月更

Docker 常用命令整合

宁在春

Docker 7月月更

Qt|模仿文字浮动字母

中国好公民st

qt 7月月更

Istio架构扩展机制

阿泽🧸

istio 7月月更

iOS中#define和const

NewBoy

ios 前端 移动端 iOS 知识体系 7月月更

java零基础入门-异常、线程(完结篇)

喵手

Java 7月月更

自研的数据产品迭代了一年多,为什么不买第三方商业数据平台产品呢?

松子(李博源)

数据中台 数据产品经理 数字化转型 数据产品

谈谈文字两端对齐的css问题

南极一块修炼千年的大冰块

7月月更

K3S - 轻量级Kubernetes集群

mengzyou

DevOps k8s k3s

C# 线程锁和单多线程简单使用

IC00

C# 7月月更

【刷题记录】19. 删除链表的倒数第 N 个结点

WangNing

7月月更

MySQL消息队列表结构

极客土豆

来,滑动到下一个小姐姐

岛上码农

flutter ios 前端 安卓开发 7月月更

Java多线程之锁优化与JUC常用类

未见花闻

7月月更

Python干货——内置函数

Java学术趴

7月日更

springboot 项目打包优化(核心 class 与依赖 jar 分离)

安逸的咸鱼

Java maven SpringBoot 2 7月月更

Redis 事务学习有感

恒山其若陋兮

7月月更

【函数式编程实战】(三)Lambda表达式原理与函数式接口精讲

小明Java问道之路

Java Lambda 后端 java8 7月月更

QDS08 curl 安装

耳东@Erdong

curl qds 7月月更

PHP 8:数组、变量、操作符、异常处理_编程语言_Deepak Vohra_InfoQ精选文章