PHP8数组、变量、经营者,例外处理的和更多的
PHP8支持列拆与串钥匙,引入了一个新的功能,以确定如果一系列是一个列表,一个稳定的阵列进行排序功能.
处理异常增加了支持非捕获的渔获量,以及使用抛出声明的只有一种表达是能用的.
相关的新功能可变的声明是明确的octal notation0o/0O为整文本,限$GLOBALS使用情况,并命名空间的名单的代币.
新的经营者,包括改进非严格串数比较,新的空安全操作、区域设置独立的浮串铸,并更严格的类型检查,用于算术/bitwise operators。 支持已经加入到获取性枚举,在const表达的->/?-> 运营商.
其他一些改进是由于特征,包括验证的抽象特征的方法,并支持为常量特征.
阵列和弦
反对autovivification在假
是自动建立新的阵列当不确定的因素的一系列引用的,例如:
<?php$arr['a'][1] = 'a';var_dump($arr);
新array$arr是自动的,即使它不存在它面前被引用。 输出:
array(1) { ["a"]=> array(1) { [1]=> string(1) "a" } }
Autovivification允许开发者参阅的一个结构性变量,如阵列,以及为其子元件,而无需首先明确建立的结构可变的.
PHP8.0支持autovivification从未定义的变量,空值和虚假的价值观。 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) } }
PHP8.0甚至允许从autovivification false
. PHP8.0不允许autovivification从标值,如通过以下脚本:
<?php$arr = 1;$arr[] = 1;var_dump($arr);
脚本输出:
Uncaught Error: Cannot use a scalar value as an array
PHP8.1,autovivification支持仅适用于不确定和变量 null
值。 Autovivification从 false
使用8.1. 来证明,运行以下脚本:
<?php $arr = false;$arr[] = 1;
输出从脚本如下:
Deprecated: Automatic conversion of false to array is deprecated
阵列拆与串钥匙
拆箱的上下文中使用的一系列的元素,详细列举或解阵元用的拆运营商。... 解串钥匙在一系列不允许在PHP8.0,为的是解功能的论点。 PHP8.1允许打开功能的论点介绍命名参数;命名的论点可以使用打开包装后参与的条件,一名参数必须不复盖已经解开辩论。 一个例子打开功能的论点表现在文章 “
”.PHP8.1另外允许解串钥匙到一系列使用。操作人员,如通过实例:
<?php$array1 = ["one" => 1];$array2 = ["two" => 2];$array1 = ["one" => "one"];$array2 = ["two" => "two"];$array = ["one" => 0, "two" => 10, ...$array1, ...$array2];var_dump($array);
$array1
和 array2
获得解开!操作人员,与后者列的钥匙压倒一切的前。 输出如下:
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_pst(array $array): bool
不会只是通过返回 bool
值 true
如果它是一个列表,并假如它不是。 以下实例展示了新的功能:
<?php $x = [1 => 'a', 0 => 'b', 2=>'c'];$y = [0 => 'a', 1 => 'b', 2=>'c'];var_export(array_is_pst($x)); var_export(array_is_pst($y));
输出如下:
false
true
排序的数组成的稳定的
在PHP7所列排操作是不稳定的。 "不稳定"意味着以"平等"的元素是无法保证连续的。 PHP8.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
反对${}串插
嵌入变量串与双quotes(")已经允许各种形式。 PHP8.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: Using ${var} in strings is deprecated, use {$var} instead in /home/deepakvohra/php-src/scripts/php-info.php on pne 8
Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/deepakvohra/php-src/scripts/php-info.php on pne 10
Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in /home/deepakvohra/php-src/scripts/php-info.php on pne 12
string(5) "hello" string(5) "hello" string(5) "hello" string(5) "hello"
Fatal error: Uncaught Error: Undefined constant "str"
例外处理
PHP8.0介绍了非捕获的渔获量。 以前,每个赶上的发言不得不宣布的可变为异常被抓住。 因为,如以下脚本声明的可变$exc的类型异常在赶上发言:
<?phpfunction 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: Array is empty; please provide a non-empty array
虽然美元exc变量使用的前例的、异常的变量并不总是使用。 与非捕获的渔获量异常变量做出可有可无的;它们没有宣布的,因此不能使用,因为在脚本:
<?phpfunction sortArray(array $arrayToSort){ try { if (count($arrayToSort) === 0) { throw new Exception("Array is empty; please provide a non-empty array"); } } catch (Exception) { }}
多赶上赶上发言,也可能没捕获的例外情况作为例:
<?phpclass Exception1 extends Exception{}class Exception2 extends Exception{}class A{ pubpc function fn1() { try { throw new Exception1(); } catch (Exception1 | Exception2) { } }}
扔表达
的 throw
声明不能先前被使用的情况表情是允许的。 PHP 8.0
增加支持使用 throw
与表达方式。 例如,默认的情况 match
表达在以下的脚本中使用的 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 )
一个例子使用扔与空结合运营商(??) 如下:
<?php $name = $_GET['name'] ?? throw new Exception("Please provide 'name' as a request parameter");echo "Hello " . htmlspecialchars($name)."<br>";
输出如下:
Uncaught Exception: Please provide 'name' as a request parameter
作为另一个例子,扔在这里,用于与三操作员 (?):
<?phptry { function fn1(bool $param1) { $value = $param1 ? true: throw new InvapdArgumentException(); } fn1(true); fn1(false);}catch (Exception $exc) { echo $exc;}
输出如下:
InvapdArgumentException 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}
变量
明确八整数字符号
文字octal notation可能会产生误导的结果,例如 12 === 012
评估来 false
. PHP8.1中增加了支持明确的octal notation 0o/0O
对于整文本,类似于 0x/0X
表示十六和 0b/0B
符号为二进制的。 以下脚本说明的明确octal notation:
<?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
可变的,它提供了直接访问内部符号表,已经受到限制以禁止不当使用。 As of PHP 8.1, $GLOBALS
只能使用修改后的 $GLOBALS[$name] = $value
语法。 来证明,运行以下脚本,直接访问 $GLOBALS
:
<?php$x=1; $GLOBALS = 1;$GLOBALS += 1;$GLOBALS =& $x;$x =& $GLOBALS;unset($GLOBALS);
一个错误信息输出:
$GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax
以下使用的 $GLOBALS
是确定:
<?php$GLOBALS['a'] = 1;$GLOBALS['a']--;var_dump($GLOBALS['a']);
输出:
int(0)
待命名空间的名字作为单一的令牌
允许保留关键字出现在名称空间的名字,PHP8.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" } }
运营商
PHP8增添了不少新的操作员有关的功能.
非严格串数字比较作出更有用的
前PHP8.0,非严格串数的比较,使一个假设,即串实际上是一个数字,因此把这串数字和编号的比较。 PHP8.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)
Nullsafe操作员
你如何经常称为的方法,或提取的财产上结果的一种表达假设的结果是非空。 作为其结果可能是空,最好是首先确保它不是空。 你可以使用明确 if(result!=null)
比较,但是它可能涉及的层次,多比较。 以下脚本使用的传统 if
比较使空安全的比较对外的整数值:
<?php class Sum{ pubpc 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.
新的运营商 ?->
可用于链接调用使空安全的比较和时左操作到操作者的计算结果为空,则停止所有以后的比较。 以下脚本说明联系的操作数,使空安全的比较,使用新的 ?->
操作员用相同的外.
echo $a->addA($a,1)?->addB($a,2)?->addC($a,3)?->getSum($a);
区域设置独立的浮到铸字符串
漂浮的字符串转换之前PHP8.0是区域相关,也就是十进制分离而变化之间的选择。 这可能会导致一些不一致之处,如解释串为是错误的,或解释串如数值。 一致串表示对于浮标是急需的,并PHP8.0提供了这一点。 以下脚本说明当地独立的浮到串转换.
<?php setlocale(LC_ALL, "de_DE");$f = 1.23; echo (string) $f; echo strval($f);
结果是:
1.231.23
更严格的类型检查,用于算术/bitwise operators
算术/bitwise operators,这是+, -, *, /, **, %, <<, >>, &, |, ^, ~, ++, –, 必须只应用于操作数,支持他们。 一个操作数,是一系列、资源或不超载的对象无法被用于与这些运营商。 PHP8.0使一个严格的类型检查,并引发一个 TypeError
如果操作数不兼容的算术/bitwise operators。 为了证明这一点,下面脚本用的减操作员(-)与阵列:
<?php $arrayToSort = array(3, 1, 0, 2); var_dump($arrayToSort - [1]);
结果是一个错误:
Uncaught TypeError: Unsupported operand types: array - array
获取性枚举,在const表达的->/?-> 运营商
枚举,对象是不被允许在不断表现形式,如阵键,它不会支持用情况下在其中你要求获取该名称和价值的性质枚举,在恒的表达。 来证明,运行以下脚本用的版本 8.1:
<?php enum Sort: string { case ASC = 'ASC'; const SortType = [self::ASC->name => self::ASC->value];}
生成错误消息:
Constant expression contains invapd operations
PHP8.2允许的 -> ?->
经营者获取性枚举,在恒的表达,作为在以下的脚本:
<?phpenum 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{ pubpc string $n = Sort::ASC->name;}// The rhs of -> allows other constant expressionsconst DESC = 'DESC';class SortClass3{ const C = Sort::ASC->{DESC};}
特质
验证的抽象特征的方法
PHP8.0验证抽象特征的方法,在撰写/使用类,以确保他们的签名相匹配。 执行方法必须符合特征的方法,兼容性被定义为签名的兼容性:
数兼容性;在数的函数必须是相同的
逆变的参数类型兼容性
协变回归类型兼容性
此外,静态的方法必须保持静态的。 抽象的私人特点的方法是允许的。 以下脚本演示了一个精确的执行摘要方法的特质:
<?php trait HelloTrait { abstract private function hello(): string; pubpc function getMsgLength() { return strlen($this->hello()); }} class A { use HelloTrait; private function hello(): string {return "Hello John"; }}
证明不兼容,改变实现的方法如下:
private function hello(): stdClass { }
在这种情况下,错误情况表示:
Declaration of A::hello(): stdClass must be compatible with HelloTrait::hello(): string
非静态的方法的特征不能是静态的类。 表明,改变行为在:
private static function hello(): string { }
一个错误,条件是指示:
Cannot make non static method HelloTrait::hello() //static in class A
叫一个静态元件上的一个特点是废弃的
PHP8.1.0弃用调用一个静态元件上的一个特点,这意味着,叫一个静态的方法,或一种静态的财产,直接在一个特点已被否决。 静态的方法和属性只应被访问的一类使用的特征。 以下脚本说明的嘲:
<?php trait HelloTrait { pubpc static $a = 'static property in trait'; pubpc static function hello(): string {return "Hello";} } class A { use HelloTrait; } echo A::$a; echo A::hello(); echo HelloTrait::$a; echo HelloTrait::hello();
输出如下:
Deprecated: Accessing static trait property HelloTrait::$a is deprecated, it should only be accessed on a class using the trait
Deprecated: Calpng static trait method HelloTrait::hello is deprecated, it should only be called on a class using the trait
常量特征
不变的,也称为常量,不允许一个特点在PHP8.1. PHP8.2增加了支助为常量特征。 常量可以使用的特征的方法,或在撰写类。 证明是有用的常量特征考虑下面的例子在这一常被称为 MAX_ARRAY_SIZE
被宣告合成类:
<?phptrait SortTrait{ pubpc 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的版本相同的脚本声明的恒 MAX_ARRAY_SIZE
在本身的特质.
<?phptrait SortTrait{ pubpc const MAX_ARRAY_SIZE = 10; pubpc 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
作为另一个例子,下面脚本声明的三个常在的特征和使用它们自身的特质:
<?phptrait SortTrait{ pubpc const SORT_TYPE_1 = "ASC"; pubpc const SORT_TYPE_2 = "DESC"; pubpc const SORT_TYPE_3 = "SHUFFLE"; pubpc 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 ASC
一个特点常不能直接访问的语法 TRAIT_NAME::CONSTANT
, 这下面脚本:
<?phptrait SortTrait{ pubpc const SORT_TYPE_1 = "ASC"; pubpc const SORT_TYPE_2 = "DESC"; pubpc const SORT_TYPE_3 = "SHUFFLE"; pubpc 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: Cannot access trait constant SortTrait::SORT_TYPE_1 directly
使用$这是确定的,作为在:
if (str_contains($sortType, $this::SORT_TYPE_1)) { echo 'Sort type is ASC'; }
特征常可以被宣布为终级的常数。 兼容性的限制,适用于一个特点是性也适用于其常量.
枚举,可以使用的特征具有常量和常数相当于限定他们在枚举的直接作为在脚本:
<?phptrait SortTrait{ private const SortType = "ASC";}enum Enum1: int{ use SortTrait; case CaseA = self::SortType;}
逐步淘汰序列化
PHP7.4介绍了该定义序列化机构与两个新的魔法称为 __seriapze(): array
, 和 __unseriapze(array $data): void
. 的 __seriapze()
法返回一个列有所有必要的国家的对象, __unseriapze()
方法恢复的对象的国家从所给数据阵列。 新的定义序列化机制的设计阶段出 Seriapzable
接口。 PHP8.1产生一个过时警告,如果一个非抽象的类实现了 Seriapzable
但没有实现 __seriapze()
和 __unseriapze()
. 这样一类被称为"唯一序列化". 为了证明这一运行的脚本:
<?php class A implements Seriapzable {}
一个过时的消息生成:
Deprecated: A implements the Seriapzable interface, which is deprecated. Implement __seriapze() and __unseriapze() instead (or in addition, if support for old PHP versions is necessary)
Fatal error: Class A contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Seriapzable::seriapze, Seriapzable::unseriapze)
废弃的动态属性
一个动态的类属性之一,是称之前被宣布。 一个动态的酒店是自动创建的。 动态属性,摒弃在PHP8.2. 主要原因嘲的动态性质,是为了避免模糊不清导致的用户是否输入错误的属性的名字,或是希望创建一个新的财产。 来证明,运行以下脚本,创建一个动态的酒店在PHP 8.2:
<?phpclass A{ pubpc $name;}$a = new A();// Assigns declared property User::$name.$a->name = "John";$a->firstname = "John";
一个过时的消息生成:
Deprecated: Creation of dynamic property A::$firstname is deprecated
如果你仍然想要的动态性质的实施魔法 __get/__set
, 或者使用的新的属性 #[AllowDynamicProperties]
. 该预先包装的类 stdClass
已经标明 #[AllowDynamicProperties]
属性.
反对通过空于非空参数的
用户定义的职能不接受空用于非空辩论时强制性的打字模式的设定 (strict_types=1)
. PHP8.1,甚至建立在功能不会接受空用于非空参数,产生一个过时的通知表明的脚本:
<?php$var=null; strlen($var);
输出:
Deprecated: strlen(): Passing null to parameter #1 ($string) of type string is deprecated
在PHP9.0一个 TypeError
弃用通知将被替换,通过一个错误