写点什么

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:565482

评论

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

九章元识大模型加速AI产业创新发展

九章云极DataCanvas

极狐GitLab 3 步优化软件价值流,谨防偷走时间、制造瓶颈的“幕后黑手”

极狐GitLab

gitlab 可视化 软件研发 价值流管理 VSM

我来泼盆冷水:正面迎击AI的时代千万别被ChatGPT割了韭菜

EquatorCoco

人工智能 信息安全 ChatGPT

如何用极狐GitLab 为 Android App 创建自动化CI/CD?详细教程来了

极狐GitLab

自动化 CI/CD Android; keystore fastlane

影响云安全的因素有哪些?如何保障云安全?

行云管家

云安全 企业上云 堡垒机 自动化运维 云管

如何理解小程序插件?微信及支付宝官方详解

没有用户名丶

AI与数据双向赋能,DingoDB成向量海时代超强引擎

九章云极DataCanvas

Nautilus Chain 主网上线,创世 ZBC 质押即将开启

威廉META

模糊测试公布结果,大众漏洞被曝光

云起无垠

网络安全 模糊测试

《APaaS应用实施方法论》电子书正式发布

明道云

Nautilus Chain 主网上线,创世 ZBC 质押即将开启

鳄鱼视界

打造数据处理新范式,DataPilot畅游数据向量海

九章云极DataCanvas

探索Reactor网络模型在当今应用领域的革新

华为云开发者联盟

开发 华为云 企业号 7 月 PK 榜 华为云开发者来联盟

阿里商旅账单系统架构设计实践

阿里技术

账单 阿里商旅 账单系统 账单数据

你的极狐GitLab SaaS上开启这些设置了吗?代码安全,安心下班!

极狐GitLab

gitlab CI/CD DevSecOps 代码安全 软件供应链安全

一文讲透 Redis 事务 (事务模式 VS Lua 脚本)

不在线第一只蜗牛

Lua脚本 redis 底层原理 Redis 可视化工具

全面构建AI能力,AIFS为AI产业发展按下“加速键”

九章云极DataCanvas

单一可信源代码托管平台的构建之道

极狐GitLab

gitlab 安全 高效 便捷 源代码管理

MobPush 厂商通道申请指南

MobTech袤博科技

大数据 华为 程序员 前端 Android;

火山引擎DataTester:三类AB实验,让企业营销拥有灵敏“网感”

字节跳动数据平台

大数据 A/B测试 对比试验 企业号 7 月 PK 榜

Apache Flink 在翼支付的实践应用

Apache Flink

大数据 flink 实时计算

下载|GitLab 2023 年 DevSecOps 全球调研报告:安全左移深入人心、AI/ML 蔚然成风

极狐GitLab

gitlab DevSecOps AI/ML 安全左移 安全实践

什么是MES,MES系统有哪些功能模块?MES系统概述

优秀

MES系统 mes

《中国民用航空业零代码应用与推广白皮书》正式发布

明道云

开源直播源码平台处理卡顿问题技巧方案_山东布谷科技创作

山东布谷科技

开源 软件开发 直播 源码搭建 直播源码

大模型时代下的全新变革

九章云极DataCanvas

Python爬虫超详细讲解(零基础入门,老年人都看的懂)

Java随想录

Java Python

在 K8S 中只会 CI 不会 CD ?3 种方式,让极狐GitLab 和 K8S 高效协同!

极狐GitLab

DevOps 云原生 k8s CI/CD 集成

Spring高手之路3——揭秘Spring依赖注入和SpEL表达式

砖业洋__

spring 依赖注入 属性注入 SpEL表达式 Bean配置

【有奖互动】开发者版本新特性,你期待哪些更新?#HDC.Together2023#

HarmonyOS开发者

HarmonyOS

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