写点什么

PHP 7 入门:数组、运算符、常量及异常处理的改进

  • 2020-09-22
  • 本文字数:11211 字

    阅读完需:约 37 分钟

PHP 7 入门:数组、运算符、常量及异常处理的改进

本文要点


  • PHP 7.0 添加了空合并运算符(??),如果第一个操作数存在且其值不为 NULL,则返回第一个操作数,否则返回第二个操作数。PHP 7.4 还增加了对空合并赋值的支持。

  • PHP 7.0 添加了一个新的比较运算符(<=>)来比较表达式。

  • PHP 7.0 增加了对 Unicode codepoint 转义语法的支持,可以将十六进制格式转换为相应的 UTF-8 编码格式。

  • 即使是从同一命名空间导入,use 语句也可以对类、函数和常量进行分组。

  • PHP 7.1 添加了一个短数组语法,可用于解包(unpacking)或析构(destructuring )数组。

  • PHP 7.1 增加了对类常量可见性的支持,这些常量可以声明为共有(public)、受保护(protected)和私有(private)。

  • PHP 7 支持在 try/catch 语句的同一 catch 块中指定多个异常。

  • 在 PHP 7.0.0 中,关键字可用作标识符。

  • PHP 7.3 引入了灵活的 Heredoc 和 Nowdoc 语法,以提高可读性。

  • PHP 7.3 在数组和 list()析构中增加了对引用赋值的支持。


这是介绍 PHP 7.x 新特性系列文章的最后一篇,在本文中,我们将讨论其对数组、运算符、常量和异常处理的改进。

空合并运算符

isset函数可用于确定一个变量是否被设置成非NULL值。通常,isset会与 PHP 的三元运算符结合使用,如下例所示。在这里,如果设置了GET请求的参数 name ,isset则返回 true,在这种情况下,变量的值被赋给变量$name,否则$name被设置成常量字符串值:


$name = isset($_GET['name']) ? $_GET['name'] : 'Deepak';echo "Hello " . htmlspecialchars($name)."<br>";
复制代码


在 PHP 7.0 中已经添加了空合并运算符(null coalescing operator??),它可用于简化此类操作。实际上,如果其第一个操作数存在且其值不为NULL,它将返回第一个操作数,否则返回第二个操作数。前面的示例可以使用??重写为:


$name = $_GET['name'] ?? 'Deepak';
复制代码


空合并运算符可以通过链式调用返回第一个定义了的值:


$name = $_GET['name'] ?? $_POST['name'] ?? 'Deepak';echo "Hello " . htmlspecialchars($name)."<br>";
复制代码


现在,创建一个脚本 ternary.php,其中包括下面所有的示例:


<?php$name = $_GET['name'] ?? 'Deepak';echo "Hello " . htmlspecialchars($name)."<br>";$name = isset($_GET['name']) ? $_GET['name'] : 'Deepak';echo "Hello " . htmlspecialchars($name)."<br>";$name = $_GET['name'] ?? $_POST['name'] ?? 'Deepak';echo "Hello " . htmlspecialchars($name)."<br>";?>
复制代码


如果不带请求参数运行脚本,那么所有示例都将输出最后指定的值:


Hello DeepakHello DeepakHello Deepak
复制代码


如果带有请求参数运行脚本,比如name=JohnSmith,那么所有的示例都会输出在$_GET['name']中接收到的请求参数:


Hello JohnSmithHello JohnSmithHello JohnSmith
复制代码

新的比较运算符

PHP 7.0 中添加了一个新的比较运算符(<=>),如果第一个表达式小于第二个表达式,则返回-1;如果两个表达式相同,则返回 0;如果第一个表达式大于第二个表达式,则返回 1。 PHP 的类型比较规则可用于执行比较。为了证明这一点,创建一个脚本 compare.php 来比较整数、浮点数和字符串的值:


<?php// 整数echo 1 <=> 1; echo "<br>";echo 1 <=> 0; echo "<br>";echo 5 <=> 10; echo "<br>";//浮点数echo 1.0 <=> 1.5;echo "<br>";echo 1.0 <=> 1.0; echo "<br>";echo 0 <=> 1.0; echo "<br>";//字符串echo "a" <=> "a";echo "<br>";echo "a" <=> "c"; echo "<br>";echo "c" <=> "a";echo "<br>";?>
复制代码


如果运行脚本,将会得到如下的比较结果:


01-1-10-10-11
复制代码

从十六进制格式到 UTF-8 的 Unicode codepoint 转换

PHP 7.0 添加了对 Unicode codepoint 转义语法的支持,该语法采用十六进制格式并返回相应的 UTF-8 编码格式。例如,在 Unicode 中,ĒU+0112表示,其中前导 0 可以省略。要尝试 Unicode codepoint 转义语法,创建一个脚本 unicode.php。将如下代码复制到该脚本中:


<?phpecho "\u{0124}";echo "\u{112}";echo "\u{13B}";echo "\u{13B}";echo "\u{014C}";?>
复制代码


如果运行脚本,将输出 UTF-8 字符串ĤĒĻĻŌ。

允许对“use”语句的别名命名空间进行分组

在 PHP 7.0 之前,从同一命名空间导入的每个类、函数和常量都必须使用单独的use语句指定。在 PHP 7.0 中,即使是从同一个命名空间导入的类、函数和常量,也可以在同一个use语句下分组。另外,从 PHP 7 开始,分组导入时允许使用尾随逗号。


举例来说,创建一个脚本 catalog.php 并声明一些属于同一命名空间的类、函数和常量,如下所示:


<?phpnamespace Catalog;class ClassA{function hello(){return "Hello from classA";}}class ClassB{function hello(){return "Hello from classB";}}class ClassC{function hello(){return "Hello from classC";}} function fn_a(){return "Message from fn_a()";}function fn_b(){return "Message from fn_b()";}function fn_c(){return "Message from fn_c()";}define("Catalog\ConstA", 1);define("Catalog\ConstB", 2);define("Catalog\ConstC", 3);?>
复制代码


如你所见,虽然使用define()声明的常量必须指定其全限定名,但对于用const声明的常量,这一点并不适用。创建另一个脚本 group-namespace.php 并导入在 catalog.php 中定义的类、函数和常量。该脚本包含 catalog.php require语句。类、函数和常量使用以下方式进行分组导入:


<?phprequire('catalog.php');use Catalog\{ClassA as A, ClassB as B, ClassC as C,};use function  Catalog\{fn_a, fn_b, fn_c,};use const Catalog\{ConstA, ConstB, ConstC,Const1};$a = new A();echo $a->hello();echo "<br/>";$b = new B();echo $b->hello();echo "<br/>";$c = new C();echo $c->hello();echo "<br/>";echo fn_a();echo "<br/>";echo fn_b();echo "<br/>";echo fn_c();echo "<br/>";echo ConstA;echo "<br/>";echo ConstB;echo "<br/>";echo ConstC;?>
复制代码


运行 group-namespace.php 脚本以访问分组导入的类、函数和常量并输出它们的值。


Hello from classAHello from classBHello from classCMessage from fn_a()Message from fn_b()Message from fn_c()123
复制代码

用于析构数组赋值的短数组语法

前面我们提到过,PHP 7 中已经不再支持使用list()解包(unpacking)字符串。无论如何,list()仍继续支持对数组进行解包或析构以赋值给变量。在 PHP 7.1 中,添加了一种短数组语法来解包或析构数组。为了演示短数组语法的用法,创建一个脚本 array_syntax.php,并为不同的“杂志”(magazine)创建一个二维数组,并为每种“杂志”分配一个 id:


$catalog = [  [1, 'Oracle Magazine'],  [2, 'Java Magazine'],  [3, 'PHP Magazine'],];
复制代码


要使用list()$catalog数组析构或解包为$id$journal_name,可以使用如下语法:


list($id1, $journal_name_1) = $catalog[0];list($id2, $journal_name_2) = $catalog[1];list($id3, $journal_name_3) = $catalog[2];
复制代码


另外,也可以使用新的数组析构语法,如下所示:


[$id1, $journal_name_1] = $catalog[0];[$id2, $journal_name_2] = $catalog[1];[$id3, $journal_name_3] = $catalog[2];
复制代码


list()函数可以在foreach()构造中使用,如下例所示:


foreach ($catalog as list($id, $journal_name)) {   echo "Journal $id is $journal_name";echo "<br/>";}
复制代码


与之等效的,使用数组语法[]foreach如下所示:


foreach ($catalog as [$id, $journal_name]) {  echo "Journal $id is $journal_name";echo "<br/>";}
复制代码


下面列出了完整的 array_syntax.php 脚本:


<?php$catalog = [  [1, 'Oracle Magazine'],  [2, 'Java Magazine'],  [3, 'PHP Magazine'],]; echo "list() syntax";echo "<br/>";list($id1, $journal_name_1) = $catalog[0];list($id2, $journal_name_2) = $catalog[1];list($id3, $journal_name_3) = $catalog[2];echo "Journal $id1 is $journal_name_1";echo "<br/>";echo "Journal $id2 is $journal_name_2";echo "<br/>";echo "Journal $id3 is $journal_name_3";echo "<br/>";echo "[] syntax";echo "<br/>";[$id1, $journal_name_1] = $catalog[0];[$id2, $journal_name_2] = $catalog[1];[$id3, $journal_name_3] = $catalog[2];echo "Journal $id1 is $journal_name_1";echo "<br/>";echo "Journal $id2 is $journal_name_2";echo "<br/>";echo "Journal $id3 is $journal_name_3";echo "<br/>";echo "list() syntax";echo "<br/>";foreach ($catalog as list($id, $journal_name)) {   echo "Journal $id is $journal_name";echo "<br/>";}echo "[] syntax";echo "<br/>";foreach ($catalog as [$id, $journal_name]) {  echo "Journal $id is $journal_name";echo "<br/>";}?>
复制代码


如果运行脚本,你将看到新的短数组语法执行与list()相同的数组拆包并输出相同的值,如下所示:


list() syntaxJournal 1 is Oracle MagazineJournal 2 is Java MagazineJournal 3 is PHP Magazine[] syntaxJournal 1 is Oracle MagazineJournal 2 is Java MagazineJournal 3 is PHP Magazinelist() syntaxJournal 1 is Oracle MagazineJournal 2 is Java MagazineJournal 3 is PHP Magazine[] syntaxJournal 1 is Oracle MagazineJournal 2 is Java MagazineJournal 3 is PHP Magazine
复制代码


与此相关,array_column函数将返回输入数组的单个列的值。在以下语法中,该列由$column_key标识


array array_column ( array $input , mixed $column_key [, mixed $index_key = NULL ] )
复制代码


PHP 7.0.0 添加了对输入参数作为对象数组的支持。为了演示这一点,创建一个脚本 array_column.php, 并声明一个带有两个字段$title$editionCatalog类。创建两个Catalog实例,并为它们设置值。然后创建一个包含两个Catalog对象的对象数组:


$catalogs = array($Catalog1, $Catalog2);
复制代码


最后,使用array_column()函数从对象数组中获取两个字段的值:


print_r(array_column($catalogs, 'title'));print_r(array_column($catalogs, 'edition'));
复制代码


array_column.php 脚本如下所示:


<?phpclass Catalog{  public $title;  public $edition;}$Catalog1 = new Catalog();$Catalog1->title = 'Oracle Magazine';$Catalog1->edition = 'January-February2018'; $Catalog2 = new Catalog();$Catalog2->title = 'Java Magazine';$Catalog2->edition = 'March-April2018';$catalogs = array($Catalog1, $Catalog2);print_r(array_column($catalogs, 'title'));print_r(array_column($catalogs, 'edition'));?>
复制代码


如果运行这个脚本,它将会输出两个Catalog对象的字段值:


Array ( [0] => Oracle Magazine [1] => Java Magazine ) Array ( [0] => January-February2018 [1] => March-April2018 )
复制代码

支持类常量可见性

PHP 7.1 增加了对类常量可见性的支持,这意味着可以将常量声明为公有(public)、受保护(protected)和私有(private)。只要声明公有常量的类是可访问的,公有常量就可以访问。受保护常量可以在同一类及其子类中访问。私有常量只能在同一类中访问。为了演示类常量可见性的用法,创建一个脚本 constants.php,并声明一个constants类。在类中声明四个常量:一个没有访问修饰符,第二个带有public访问修饰符,第三个带有protected修饰符,第四个带有private访问修饰符:


const A = 'A';  public const B = 2;  protected const C = 'C';  private const D = 4;
复制代码


类常量的默认可见性是public。现在定义三个函数:带有公有访问修饰符的fn_a()、带有私有访问修饰符的fn_b()、带受保护访问修饰符的fn_c()。每个函数都输出先前定义的四个常量的值:


echo constants::A;echo constants::B;echo constants::C;echo constants::D;
复制代码


从 fn_a() 调用 fn_b() 。


$this->fn_b();


从 fn_b() 调用函数 fn_c() 。


$this->fn_c();


为了说明类中声明的所有常量都可以从同一个类中访问,而不管其所使用的可见性或访问修饰符如何,创建一个类常量实例并调用fn_a()函数,该函数反过来调用fn_b(),后者又调用fn_c()


$constants=new constants();$constants->fn_a();
复制代码


为了说明私有常量在声明它们的同一个类中是可访问的,受保护常量只能从子类和同一个声明类中访问,声明一个类ClassA,并在函数fn_a()中输出每个常量的值:


class ClassA{public function fn_a(){echo constants::A;echo constants::B;echo constants::C; echo constants::D;}
复制代码


最后,为了说明公有和受保护的常量可以从子类中访问,而私有常量不能,声明constants类的一个子类并在函数fn_d()中输出每个常量的值:


class ClassB extends constants{public function fn_d(){echo constants::A;echo constants::B;echo constants::C;echo constants::D;}
复制代码


constants.php 脚本如下所示:


<?phpclass constants{  const A = 'A';  public const B = 2;  protected const C = 'C';  private const D = 4;public function fn_a(){echo constants::A;echo "<br/>";echo constants::B;echo "<br/>";echo constants::C;echo "<br/>";echo constants::D;echo "<br/>";$this->fn_b();}private function fn_b(){echo constants::A;echo "<br/>";echo constants::B;echo "<br/>";echo constants::C;echo "<br/>";echo constants::D;echo "<br/>";$this->fn_c();}protected function fn_c(){echo constants::A;echo "<br/>";echo constants::B;echo "<br/>";echo constants::C;echo "<br/>";echo constants::D;echo "<br/>";}}class ClassA{public function fn_a(){echo constants::A;echo "<br/>";echo constants::B;echo "<br/>";//echo constants::C; Uncaught Error: Cannot access protected const constants::C echo "<br/>";//echo constants::D;Uncaught Error: Cannot access private const constants::Decho "<br/>";}}class ClassB extends constants{public function fn_d(){echo constants::A;echo "<br/>";echo constants::B;echo "<br/>";echo constants::C;echo "<br/>";//echo constants::D;Uncaught Error: Cannot access private const constants::Decho "<br/>";} }$constants=new constants();$constants->fn_a();$classA=new ClassA();$classA->fn_a();$classB=new ClassB();$classB->fn_d();?>
复制代码


如果你尝试运行该脚本,如下所示的 echo 语句将生成这样的错误:Uncaught Error: Cannot access protected const constants::C.


class ClassA{  public function fn_a(){   echo constants::C;   }..}
复制代码


作为一个受保护的常量,constants::C不能从任何非constants派生的类中访问。现在,注释掉该语句并重新运行脚本。如下语句将导致脚本生成另一个错误Uncaught Error: Cannot access private const constants::D


class ClassA{   public function fn_a(){  echo constants::D;   }}
复制代码


作为一个私有常量,constants::D不能从任何其他类中访问。注释掉该语句,并再次运行脚本。脚本现在会生成另一个错误Uncaught Error: Cannot access private const constants::D


class ClassB extends constants{public function fn_d(){ ...echo constants::D; }…}
复制代码


constants::D是一个私有常量,不能从子类中访问它。注释掉该语句,并重新运行脚本。现在,可以得到如下输出:


A2C4A2C4A2C4A2



A2C
复制代码

每个 catch 块包含多个异常

现在,可以在try/catch语句的同一个catch块中指定多个异常,多个异常使用管道字符“|”分隔。如果需要以相同的方式处理多个异常,那么该特性会非常有用。为了演示多异常 catch 块的用法,创建一个脚本 multi-catch-exception.php,并将如下代码复制到其中。该脚本声明了两个自定义的异常类和一个 try/catch 语句,该语句在另一个类(MultiCatch)的test()函数中,且该函数在 catch 块中声明了多个异常:


try {          throw new CustomException_2();      } catch (CustomException | CustomException_2 $e) {            var_dump(get_class($e));      }
复制代码


脚本 multi-catch-exception.php 如下所示:


<?phpclass CustomException extends Exception { }class CustomException_2 extends Exception { }class MultiCatch {  public function test() {      try {          throw new CustomException_2();      } catch (CustomException | CustomException_2 $e) {            var_dump(get_class($e));        }  }}$multiCatch = new MultiCatch;$multiCatch->test();?>
复制代码


如果运行该脚本,在 try 块中抛出的异常将会在 catch 块中被捕获,如下所示:


string(17) "CustomException_2" 
复制代码

改进了扩展加载语法

php.ini中可用的扩展加载语法已经得到了改进。共享扩展不再需要.dll(在 Windows 上)和.so(在 Unix 上)后缀。例如,可以用如下方式指定 MySQL 数据库和 Oracle 数据库的扩展:


extension=mysqliextension=oci8_12c
复制代码

关键字作为标识符

在 PHP 7.0.0 中,关键字可以用作类、接口和特征(trait)的属性、常量和方法名称。为了演示这一点,创建一个脚本 reserved_restriction.php,并将以下代码复制到该脚本中。该脚本使用保留关键字(intiterable)来声明变量名。它还声明了一个常量null(关键字)和一个true(关键字)函数。


<?phpclass Catalog {  public $int = 'hello ' . 'php';  public $iterable = '';  const null = 'null';  function true() {  }}$catalog=new Catalog(); $catalog->true();?>
复制代码


如果运行该脚本,不会输出错误信息。使用关键字作为标识符可能的一个例外是,不能将常量命名为 class。为了演示这一点,在前面的脚本中添加以下代码:


const class=1;
复制代码


如果运行该脚本,将生成以下错误信息:


A class constant must not be called 'class'; it is reserved for class name fetching.

灵活的 Heredoc 和 Nowdoc 语法

让我们先回顾一下HeredocNowdoc语法。Heredoc类似于双引号字符串,用开始和结束标记代替引号。使用 heredoc,在<<<开始运算符之后,可以指定一个任意标识符,后跟一个换行符。随后是一个字符串,并且以相同的标识符结束引号。NowdocHeredoc相似,不同之处在于开始标记放在单引号''中,并且在Nowdoc内不进行任何解析。


PHP 7.3 引入了灵活的HeredocNowdoc语法,以提高可读性,并进行了如下的改进:


  1. 结束标记不需要后跟分号(”;“)。

  2. 结束标记不需要后跟换行符。

  3. 结束标记可以用制表符或空格缩进。制表符和空格不能混用。文档中的字符串文本可以缩进到与结束标记的缩进级别相同或更高。

  4. 结束标识符由与开始标识符相同的连续独立标记标识。


接下来,我们将用几个例子来演示下新的语法。但首先回顾一下旧语法:


print <<<EOT


Heredoc is similar to double-quoted string, with start and end markers replacing quotes.


EOT;


Heredoc 也可以赋值给变量:


<?phpclass A {  public $a = <<<EOTAn example of heredoc as a variable value.EOT;}?>
复制代码


下面是一个使用新语法的 Heredoc 示例。


<?php$str = <<<EOD  The heredoc string  EOD;echo <<<EOT      The heredoc string  line 1     The heredoc string  line 2    The heredoc string  line 3    EOT?>
复制代码


相反,下面的脚本并不是一个有效的 Heredoc 语法,会生成这样的错误:Parse error: Invalid indentation - tabs and spaces cannot be mixed.


<?php{   echo <<<END            Heredoc text              END;}?>
复制代码


下面是Nowdoc老语法的一个示例。


print <<<'EOT'


Nowdoc is similar to heredoc except that the start marker is enclosed in a single quote '' and no parsing is done inside a nowdoc.


EOT;


新 Nowdoc 语法的示例如下所示。


<?php$str = <<<EOD  The heredoc string  EOD;echo <<<'EOT'      The nowdoc string  line 1     The nowdoc string  line 2    The nowdoc string  line 3    'EOT' ?>
复制代码


由于在 nowdoc 中不进行任何解析,因此下面示例的 nowdoc 字符串中包含冗余代码:


<?php$str = <<<'EOD'The heredoc  text.EOD;class A{  var $a;  var $b;  function __construct()  {        $this->a = 'A';        $this->b = array('B1', 'B2', 'B3');  }}$A = new A();$c = 'C';echo <<<'EOT'    Value of variable is "$c". Value of a variable from a class A is  "$A->a".   Value of an array element from class A is "{$A->b[2]}".  Unicode  for 'B' is U+0042   EOT?>
复制代码


由于未执行任何解析,因此前面的脚本会生成如下的输出。


Value of variable is "$c". Value of a variable from a class A is "$A->a". Value of an array element from class A is "{$A->b[2]}". Unicode for 'B' is U+0042


如前所述,heredoc 和 nowdoc 主体缩进级别必须至少与结束标记的缩进级别相同。为了证明这一点,运行如下脚本。


<?phpecho <<<'EOT'    Line 1   Line 2  Line 3   EOT?>
复制代码


在这种情况下,会产生以下错误:


Invalid body indentation level (expecting an indentation level of at least 5

支持数组析构中的引用赋值

PHP 7.3 增加了对数组和list()析构中引用赋值的支持。首先让我们回顾一下什么是数组/列表(array/list)析构中的赋值。在下面的脚本中,将对数组进行析构,并将其元素值赋给一个列表:


<?phplist($a[], $a[], $a[]) = ['A', 2, 3];var_dump($a);?>
复制代码


var_dump语句生成如下输出:


array(3) { [0]=> string(1) "A" [1]=> int(2) [2]=> int(3) }


现在,让我们来看一个新语法的示例:


list(&$a, [$b, &$c]) = $d


在本例中,列表元素$a$c是通过引用赋值的。例如,创建以下脚本,其中$array[1]元素通过引用$bvariable赋值。这意味着,如果为$b赋了一个新值,则新值也将赋给$array[1]


<?php$array = ['A', 2];list($a, &$b) = $array;echo $a;echo "<br/>";echo $b;echo "<br/>";echo $array[1];$b='b';echo "<br/>";echo $array[1];
复制代码


该脚本的输出如下:


A22b
复制代码


如果不通过引用赋值而运行相同的脚本,则输出将不同。


list($a, $b) = $array;


使用上述赋值的输出如下:


A222
复制代码


最后,让我们考虑一个数组析构中引用赋值的示例。在下面的脚本中,数组元素通过引用变量b 的值被更改了,那么数组元素的值也会随之改变。


<?php$array = [1, &$b]; $b='B';echo $array[0];echo "<br/>";echo $array[1];$b=2;echo "<br/>";echo $array[1];
复制代码


运行该脚本,将会得到如下的输出:


1B2
复制代码

Instanceof 接受字面量

让我们首先回顾一下instanceof运算符。在下面的脚本中,instanceof用于确定对象是否为类 A 的实例:


<?phpclass A{}$obj = new A();echo ($obj instanceof A);?>
复制代码


如果运行该脚本,将输出 1。


PHP 7.3 添加了对将字面量用作第一个操作数的支持。在下面的脚本中,instanceof的第一个操作数是一个字符串字面量:


<?phpclass A{}echo ('Hello PHP' instanceof A); ?>
复制代码


如果运行该脚本,将输出FALSE。如果第一个操作数是一个字面量,instanceof的输出总是FALSE

空合并赋值

我们前面讨论过在 PHP 7.0 中引入的空合并运算符??。PHP 7.4 采用空合并运算符??进一步添加了对空合并赋值的支持。比如,考虑以下情况。使用isset()来确定是否设置了数组键,如果没有设置,则为其设置一个值


if (!isset($a['4'])) {    $a['4'] = setDefault();}
复制代码


下面的脚本演示了如何对具有相同条件设置的数组键运用空合并赋值:


<?php$a = array('1' => 'one', '2' => 'two', '3' => 'three');$a['4'] ??= setDefault();function setDefault(){     return 'four';}var_dump($a);//array(4) { [1]=> string(3) "one" [2]=> string(3) "two" [3]=> string(5) "three" [4]=> string(4) "four" }?>
复制代码

数字字面量分隔符

具有多个数字的数字字面量可能会由于长度的关系而变得无法识别,这可能会使调试变得相当困难。PHP 7.4 引入了下划线作为数字字面量的分隔符,以提高代码的可读性。下面的脚本在不同类型的变量中使用了数字分隔符“_”。


$_1=10_;       // 用在末尾$_2=1__2;       // 用在下划线后$_3=5_.0; 1._0; // 用在小数点后$_4=0x_123;     //用在x后$_5=0b_111;     //用在b后
复制代码


使用下划线作为数字字面量分隔符的唯一要求是它必须出现在两个数字之间。具体地说,它不能用在数字的末尾,也不能出现在另一个下划线或小数点旁边。变量名仍然可以以下划线开头。下面列举以错误方式将"_"用作数字字面量分隔符的所有示例:


$_1=10_;       //  用在末尾$_2=1__2;       // 用在下划线旁$_3=5_.0; 1._0; // 用在小数点后$_4=0x_123;     // 用在x后$_5=0b_111;     // 用在b后$_6=2_e3; 2e_3; // 用在e旁
复制代码


在词法分析期间,数字字面量中的下划线将会被删除。

用于数组内解包的扩展运算符

在函数签名中,已经支持用由三个连续点(…)表示的扩展运算符对参数进行解包。PHP 7.4 增加了对扩展操作符的支持,以解包数组的元素。数组中支持的扩展运算符主要有如下特征:


  • 实现Traversable的数组和对象可以与扩展运算符一起使用。

  • 扩展运算符可以在数组的任何位置使用,在元素之前或之后,甚至是连续使用都可以。

  • 它可以与数组语法(array())和短语法([])一起使用。

  • 函数返回的数组可以用 score 运算符解包。

  • 数组不能通过引用解包。如果要解包的数组元素是通过引用存储的,那么解包之后,它们还将继续通过引用存储。

  • 不支持字符串键。


下面的脚本演示了扩展操作符的使用。数组元素...$cd使用了扩展操作符。...getArr()对函数返回的数组进行解包。


<?php$cd = ['c', 'd'];$af = ['a', 'b', ...$cd,'e','f'];var_dump($af);  function getArr() {  return ['c', 'd'];}$af = ['a', 'b',...getArr(), 'e','f'];  var_dump($af); ?>
复制代码


每个 var_dump 语句输出均为:


array(6) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> string(1) "c" [3]=> string(1) "d" [4]=> string(1) "e" [5]=> string(1) "f" }


为了验证字符串键不能与扩展操作符一起使用,请运行如下脚本:


<?php$cd = array("c" => "c","d" => "d");$af = ['a', 'b', ...$cd,'e','f'];var_dump($af);
复制代码


将会显示如下的错误信息:


Uncaught Error: Cannot unpack array with string keys

不再推荐使用花括号语法来访问数组元素

PHP 7.4 不推荐使用花括号来访问数组元素和字符串偏移量。无论如何,花括号语法只具有有限的功能。例如,它不能用于创建数组或将元素推入数组,也不能用于列表赋值。以下脚本仍可以使用,并能生成预期的输出字符串(1)“ a”。


<?php$arr = ['a', 'b', 'c'];var_dump($arr{0});
复制代码


但它也会显示一条警告信息:


Deprecated: Array and string offset access syntax with curly braces is deprecated

总结

在关于 PHP 7 系列的五篇文章中,我们已经按照特性类别分组的形式探讨了 PHP 7.x 中显著的新特性。在第一篇文章《PHP 7入门:OOP改进》中,我们设置了运行 PHP 7.x 脚本的环境,并介绍了与面向对象编程相关的改进。在第二篇文章《PHP 7 :类和接口的增强》中,我们介绍了对类和接口的改进。在第三篇文章《PHP 7:类型的新特性》中,我们介绍了 PHP 类型系统的改进。在第四篇《PHP 7:函数改进》中,我们介绍了与函数相关的改进。在本系列的最后一篇文章中,我们将介绍之前文章中没有涉及的改进,其中包括对数组、运算符、常量和异常处理的改进。


PHP 8.0 预计将于 2020 年 12 月初发布,并会提供一组新特性,但在此之前,仍需要学习使用 PHP 7.x。


作者介绍


Deepak Vohra 是一位 Sun 认证的 Java 程序员和 Sun 认证的 Web 组件开发人员。Deepak 在 WebLogic Developer’s Journal、XML Journal、ONJava、java.net、IBM developerWorks、Java Developer’s Journal、Oracle Magazine 和 devx 上都发表过 Java 和 Java EE 相关的技术文章。Deepak 还是一名 Docker 导师,已出版了五本关于 Docker 的书籍。Deepak 还发表了几篇关于 PHP 的文章,以及一本面向 PHP 和 Java 开发人员的 Ruby on Rails 书籍。


原文链接:


https://www.infoq.com/articles/php-7-array-operators/


相关阅读


PHP 7 入门:新特性简介


PHP 7 入门:类和接口的增强


2020-09-22 14:565278

评论

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

第三周作业

大肚皮狒狒

软件测试|人工智能如何帮助测试工程师解决问题?

霍格沃兹测试开发学社

加入DevRun软件开发流水线实战营,即刻开启你的职场竞争力之旅!

科技热闻

一文看懂:小程序游戏需要版号吗?

FN0

FuncGPT(慧函数)教你用Mybatis进行一对一查询映射处理

SoFlu软件机器人

一张图读懂TuGraph Analytics开源技术架构

TuGraphAnalytics

大数据 分布式 流计算 图计算 流图

生成式AI:内容创作新革命

百度开发者中心

自然语言处理 内容 #人工智能 文心一言

生成式AI助力高效写作

百度开发者中心

大模型 #人工智能 ChatGPT 生成式AI

软件测试|如何使用ChatGPT生成思维导图

霍格沃兹测试开发学社

2023年科技趋势展望报告,这几个领域程序员可以恰饭

互联网工科生

人工智能 软件开发 麦肯锡

唯一受邀参会通信服务商!融云出席数字经济头部盛会「中数大会」并发言

融云 RongCloud

人工智能 互联网 通信 数字 融云

ETL 小技巧:文件输出插件数据写入空闲时间阈值配置及作用

大河

缓冲区 ETL bboss 文件输出

头脑风暴小工具-影响地图

Bruce Talk

敏捷开发 Agile Product Owner 影响地图

华为云GaussDB打造最可信的数据库,给世界一个更优选择

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 8 月 PK 榜

Easysearch 跨集群复制实战

极限实验室

easysearch

常用的国内外组态软件推荐

2D3D前端可视化开发

物联网 组态软件 工业组态软件 web组态软件 SCADA

cad设计绘图必备:AutoCAD 2024激活中文附补丁安装教程

mac大玩家j

Mac软件 CAD绘图 CAD设计 cad工具

《守望先锋 2》性能提升高达33%!英特尔锐炫从未止步

E科讯

​Elastic Stack最佳实践系列:Beats->ES,一个更轻型的架构选择

腾讯云大数据

ES

容器化微服务:用Kubernetes实现弹性部署

高端章鱼哥

Kubernetes 微服务 容器化

社交语聊平台运营,需要哪些资质?语聊APP原生开发和混合uniapp开发的利弊分析

山东布谷科技胡月

语音聊天系统软件开发 语音直播平台开发 语音聊天室开发 语音程序源码 社交直播APP开发

Last Week in Milvus

Zilliz

非结构化数据 开源社区 Milvus Zilliz 向量数据库

九科信息成功签约中交房地产集团有限公司RPA项目

九科Ninetech

首批通过!柏睿数据旗下数据库产品获强制性国标最高级别认证

新消费日报

电脑硬件迭代快,对仿真软件有什么影响?

智造软件

仿真软件 电脑硬件 结构仿真 电脑配置 硬件配置

生成式AI引领未来传媒业发展趋势

百度开发者中心

媒体 #人工智能 生成式AI 文心一言

几款常用基于Web的组态编辑器

2D3D前端可视化开发

物联网 web组态 web组态软件 组态可视化 web组态编辑器

云服务之PaaS:PaaS怎么帮助企业走向云

高端章鱼哥

云计算 低代码 PaaS JNPF

和鲸 × 临床医学丨“人”作为一生命体在 AI for Science 过程中的作用与交互

ModelWhale

数据科学 临床医学 AI for Science 交叉学科 临床研究

又一可视化低代码神器!云耀云服务器L实例正式发布

mecchi

软件开发 云主机 云服务器 博客搭建

PHP 7 入门:数组、运算符、常量及异常处理的改进_语言 & 开发_Deepak Vohra_InfoQ精选文章