二、PHP7 的新特性

PHP7 引入了新的特性,可以帮助程序员编写高性能和高效的代码。另外,一些旧式的特性被完全删除,如果使用 PHP7,将抛出一个错误。大多数致命错误现在都是异常,因此 PHP 不再显示丑陋的致命错误消息;取而代之的是,它将通过一个包含可用详细信息的异常。

在本章中,我们将介绍以下主题:

  • 类型提示
  • 名称空间和组使用声明
  • 匿名类
  • 旧式构造函数弃用
  • 宇宙飞船操作员
  • 空合并运算符
  • 统一变量语法
  • 杂项变动

面向对象特性

PHP7 引入了一些新的 OOP 特性,使开发人员能够编写干净有效的代码。在本节中,我们将讨论这些特性。

类型提示

在 PHP7 之前,不需要声明传递给函数或类方法的参数的数据类型。此外,没有必要提及返回数据类型。任何数据类型都可以传递给函数或方法并从中返回。这是 PHP 中的一个巨大问题,在 PHP 中,并不总是清楚应该从函数或方法传递或接收哪些数据类型。为了解决这个问题,PHP7 引入了类型提示。到目前为止,引入了两种类型的提示:标量和返回类型提示。这些将在以下章节中讨论。

类型提示在 OOP 和过程 PHP 中都是特性,因为它可以用于过程函数和对象方法。

标量类型提示

PHP7 使得可以对函数和方法的整数、浮点数、字符串和布尔值使用标量类型提示。让我们看一下以下示例:

class Person
{
  public function age(int $age)
  {
    return $age;
    }

  public function name(string $name)
  {
    return $name;
    }

  public function isAlive(bool $alive)
  {
    return $alive;
    }

}

$person = new Person();
echo $person->name('Altaf Hussain');
echo $person->age(30);
echo $person->isAlive(TRUE);

在前面的代码中,我们创建了一个Person类。我们有三个方法,每个方法都接收不同的参数,这些参数的数据类型是用它们定义的,正如前面代码中强调的那样。如果您运行前面的代码,它将正常工作,因为我们将为每个方法传递所需的数据类型。

年龄可以是浮动的,例如30.5年;因此,如果我们将一个浮点数传递给age方法,它仍然会工作,如下所示:

echo $person->age(30.5);

为什么呢?这是因为,默认情况下,标量类型提示是非限制性的。这意味着我们可以将浮点数传递给需要整数的方法。

为了使其更具限制性,可以在文件顶部放置以下单行代码:

declare(strict_types = 1);

现在,如果我们将一个浮点数传递给age函数,我们将得到一个未捕获类型错误,这是一个致命错误,告诉我们Person::age必须是给定浮点数的 int 类型。如果我们将字符串传递给非字符串类型的方法,将生成类似的错误。考虑下面的例子:

echo $person->isAlive('true');

前面的代码将在向其传递字符串时生成致命错误。

返回类型提示

PHP7 的另一个重要特性是能够定义函数或方法的返回数据类型。它的行为方式与标量类型提示的行为方式相同。让我们稍微修改一下Person类,以了解返回类型提示,如下所示:

class Person
{
  public function age(float $age) : string
  {
    return 'Age is '.$age;
  }

  public function name(string $name) : string
  {
    return $name;
    }

  public function isAlive(bool $alive) : string
  {
    return ($alive) ? 'Yes' : 'No';
  }

}

类中的更改将突出显示。返回类型使用: data-type语法定义。返回类型是否与标量类型相同并不重要。只要它们匹配各自的数据类型,它们就可以不同。

现在,让我们尝试一个对象返回类型的示例。考虑前一个 Tyt0f 类,并向其中添加一个 Tyl T1 方法。另外,我们将在同一个文件中添加一个新类Address,如下面的代码所示:

class Address 
{
 public function getAddress()
 {
 return ['street' => 'Street 1', 'country' => 'Pak'];
 }
}

class Person
{
  public function age(float $age) : string
  {
    return 'Age is '.$age;
  }

  public function name(string $name) : string
  {
    return $name;
  }

  public function isAlive(bool $alive) : string
  {
    return ($alive) ? 'Yes' : 'No';
  }

 public function getAddress() : Address
 {
 return new Address();
 }
}

添加到Person类和新Address类的附加代码突出显示。现在,如果我们调用Person类的getAddress方法,它将完美地工作并且不会抛出错误。但是,假设我们更改 return 语句,如下所示:

public function getAddress() : Address
{
  return ['street' => 'Street 1', 'country' => 'Pak'];
}

在这种情况下,前面的方法将抛出一个类似于以下内容的未捕获异常:

Fatal error: Uncaught TypeError: Return value of Person::getAddress() must be an instance of Address, array returned

这是因为我们返回的是数组而不是Address对象。现在的问题是:为什么要使用类型提示?使用类型提示的最大优点是,它总是能够避免意外地向方法或函数传递或返回错误和意外的数据。

从前面的例子中可以看出,这使得代码变得清晰,通过查看方法的声明,可以准确地知道应该向每个方法传递哪些数据类型,以及通过查看每个方法的代码或注释(如果有的话)返回什么样的数据。

名称空间和组使用声明

在一个非常大的代码库中,类被划分为名称空间,这使得它们易于管理和使用。但是,如果名称空间中的类太多,并且需要使用其中的 10 个,那么必须为所有这些类键入完整的 use 语句。

在 PHP 中,不需要像其他编程语言那样,按照名称空间划分子文件夹中的类。名称空间只是提供了类的逻辑分离。但是,我们并不局限于根据名称空间将类放置在子文件夹中。

例如,我们有一个Publishers/Packt名称空间和类BookEbookVideoPresentation。此外,我们还有一个functions.php文件,它具有我们的正常功能,并且位于相同的Publishers/Packt名称空间中。另一个文件constants.php具有应用所需的常量值,并且位于同一命名空间中。每个类及functions.phpconstants.php文件的代码如下:

//book.php
namespace Publishers\Packt;

class Book 
{
  public function get() : string
  {
    return get_class();
  }
}

现在Ebook类的代码如下:

//ebook.php
namespace Publishers\Packt;

class Ebook 
{
  public function get() : string
  {
    return get_class();
  }
}

Video类的代码如下:

//presentation.php
namespace Publishers\Packt;

class Video 
{
  public function get() : string
  {
    return get_class();
  }
}

类似地,presentation类的代码如下:

//presentation.php
namespace Publishers\Packt;

class Presentation 
{
  public function get() : string
  {
    return get_class();
  }
}

这四个类都有相同的方法,使用 PHP 内置的get_class()函数返回类的名称。

现在,在functions.php文件中添加以下两个函数:

//functions.php

namespace Publishers\Packt;

function getBook() : string
{
  return 'PHP 7';
}
function saveBook(string $book) : string
{
  return $book.' is saved';
}

现在,我们将以下代码添加到constants.php文件中:

//constants.php

namespace Publishers/Packt;

const COUNT = 10;
const KEY = '123DGHtiop09847';
const URL = 'https://www.Packtpub.com/';

functions.phpconstants.php中的代码都是不言自明的。请注意,每个文件的顶部都有一个namespace Publishers/Packt行,这使得这些类、函数和常量属于这个名称空间。

现在,有三种方法可以使用类、函数和常量。让我们考虑一下每一个问题。

请看下面的代码:

//Instantiate objects for each class in namespace

$book = new Publishers\Packt\Book();
$ebook = new Publishers\Packt\Ebook();
$video = new Publishers\Packt\Video();
$presentation = new Publishers\Packt\Presentation();

//Use functions in namespace

echo Publishers/Packt/getBook();
echo Publishers/Packt/saveBook('PHP 7 High Performance');

//Use constants

echo Publishers\Packt\COUNT;
echo Publishers\Packt\KEY;

在前面的代码中,我们在创建对象或使用函数和常量时直接使用名称空间名称。代码看起来不错,但很凌乱。名称空间无处不在,如果我们有很多名称空间,它看起来会很难看,可读性也会受到影响。

我们在前面的代码中没有包含类文件。可以使用include语句或 PHP 的__autoload函数包含所有文件。

现在,让我们重写前面的代码,使其更具可读性,如下所示:

use Publishers\Packt\Book;
use Publishers\Packt\Ebook;
use Publishers\Packt\Video;
use Publishers\Packt\Presentation;
use function Publishers\Packt\getBook;
use function Publishers\Packt\saveBook;
use const Publishers\Packt\COUNT;
use const Publishers\Packt\KEY;

$book = new Book();
$ebook = new Ebook(();
$video = new Video();
$pres = new Presentation();

echo getBook();
echo saveBook('PHP 7 High Performance');

echo COUNT; 
echo KEY;

在前面的代码的顶部,我们对命名空间中的特定类、函数和常量使用了 PHP 语句。但是,我们仍然为每个类、函数和/或常量编写了重复的代码行。这可能会导致我们在文件的顶部有大量的 use 语句,而且总体上说来冗长不好。

为了解决这个问题,PHP7 引入了组使用声明。有三种类型的组使用声明:

  • 非混合使用声明
  • 混合使用声明
  • 复合使用声明

非混合组使用声明

考虑到我们在命名空间中有不同类型的特征,因为在命名空间中有类、函数和联系人。在非混合组使用声明中,我们使用use语句分别声明它们。为了更好地理解它,请查看以下代码:

use Publishers\Packt\{ Book, Ebook, Video, Presentation };
use function Publishers\Packt\{ getBook, saveBook };
use const Publishers\Packt\{ COUNT, KEY };

命名空间中有三种类型的特性:类、函数和常量。因此,我们使用了单独的组use声明语句来使用它们。代码现在看起来更干净、更有组织性和可读性,并且不需要太多重复键入。

混合组使用声明

在这个声明中,我们将所有类型组合成一个use语句。请看下面的代码:

use Publishers\Packt\{ 
  Book,
  Ebook,
  Video,
  Presentation,
  function getBook,
  function saveBook,
  const COUNT,
  const KEY
};

复合名称空间声明

为了理解 Apple T0 复合命名空间声明,我们将考虑以下标准。

假设我们在Publishers\Packt\Paper名称空间中有一个Book类。此外,我们在Publishers\Packt\Electronic名称空间中有一个Ebook类。VideoPresentation类位于Publishers\Packt\Media命名空间中。因此,要使用这些类,我们将使用以下代码:

use Publishers\Packt\Paper\Book;
use Publishers\Packt\Electronic\Ebook;
use Publishers\Packt\Media\{Video,Presentation};

在复合名称空间声明中,我们可以使用前面的名称空间,如下所示:

use Publishers\Packt\{
  Paper\Book,
  Electronic\Ebook,
  Media\Video,
  Media\Presentation
};

它更加优雅和清晰,如果名称空间名称很长,则不需要额外键入。

匿名类

匿名类是同时声明和实例化的类。它没有名称,可以具有普通类的全部功能。这些类在需要执行单个一次性小任务时非常有用,不需要为其编写完整的类。

创建匿名类时,它没有命名,但在 PHP 中内部命名,并根据其在内存块中的地址使用唯一的引用。例如,匿名类的内部名称可以是class@0x4f6a8d124

该类的语法与命名类的语法相同,但只缺少该类的名称,如下语法所示:

new class(argument) { definition };

让我们看一个匿名类的基本且非常简单的示例,如下所示:

$name = new class() {
  public function __construct()
  {
    echo 'Altaf Hussain';
  }
};

前面的代码将只显示输出为Altaf Hussain

参数也可以传递给匿名类构造函数,如下代码所示:

$name = new class('Altaf Hussain') {
  public function __construct(string $name)
  {
    echo $name;
  }
};

这将为我们提供与第一个示例相同的输出。

匿名类可以扩展其他类,并且具有与普通命名类相同的父子类。再举一个例子,;请看以下内容:

class Packt
{
  protected $number;

  public function __construct()
  {
    echo 'I am parent constructor';
  }

  public function getNumber() : float
  {
    return $this->number;
  }
}

$number = new class(5) extends packt
{
  public function __construct(float $number)
  {
    parent::__construct();
    $this->number = $number;
  }
};

echo $number->getNumber();

前面的代码将显示I am parent constructor5。可以看出,我们以扩展命名类的方式扩展了Packt类。此外,我们还可以使用匿名类对象访问匿名类中的publicprotected属性和方法以及公共属性和方法。

匿名类也可以实现接口,与命名类相同。让我们先创建一个接口。运行以下命令:

interface Publishers
{
  public function __construct(string $name, string $address);
  public function getName();
  public function getAddress();
}

现在,让我们修改Packt类,如下所示。我们添加了突出显示的代码:

class Packt
{
  protected $number;
  protected $name;
  protected $address;
  public function …
}

代码的其余部分与第一个Packt类相同。现在,让我们创建一个匿名类,它将实现前面代码中创建的Publishers接口,并扩展新的Packt类,如下所示:

$info = new class('Altaf Hussain', 'Islamabad, Pakistan')extends packt implements Publishers
{
  public function __construct(string $name, string $address)
  {
    $this->name = $name;
    $this->address = $address;
  }

  public function getName() : string
  {
  return $this->name;
  }

  public function getAddress() : string
  {
  return $this->address;
  }
}

echo $info->getName(). ' '.$info->getAddress();

前面的代码是不言自明的,将与地址一起输出Altaf Hussain

可以在另一个类中使用匿名类,如下所示:

class Math
{
  public $first_number = 10;
  public $second_number = 20;

  public function add() : float
  {
    return $this->first_number + $this->second_number;
  }

  public function multiply_sum()
  {
    return new class() extends Math
    {
      public function multiply(float $third_number) : float
      {
        return $this->add() * $third_number;
      }
    };
  }
}

$math = new Math();
echo $math->multiply_sum()->multiply(2);

前面的代码将返回60。这是怎么发生的?Math类有一个multiply_sum方法返回匿名类的对象。这个匿名类是从Math类扩展而来的,它有一个multiply方法。因此,我们的echo语句可以分为两部分:第一部分是$math->multiply_sum(),它返回匿名类的对象,第二部分是->multiply(2),在其中我们链接了这个对象以调用匿名类的multiply方法以及一个值为2的参数。

在前面的案例中,Math类可以称为外部类,匿名类可以称为内部类。但是,请记住,内部类不需要扩展外部类。在前面的示例中,我们扩展它只是为了确保内部类可以通过扩展外部类来访问外部类的属性和方法。

旧式建造师不赞成

回到 PHP4,类的构造函数与类的方法同名。它仍然在使用,并且在 PHP 的 5.6 版本之前一直有效。然而,现在在 PHP7 中,它被弃用了。让我们举一个例子,如下所示:

class Packt
{
  public function packt()
  {
    echo 'I am an old style constructor';
  }
}

$packt = new Packt();

前面的代码将显示带有不推荐消息的输出I am an old style constructor,如下所示:

Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; Packt has a deprecated constructor in…

但是,仍然调用旧式构造函数。现在,我们将 PHP__construct方法添加到我们的类中,如下所示:

class Packt
{
  public function __construct()
  {
    echo 'I am default constructor';
  }

  public function packt()
  {
    echo 'I am just a normal class method';
  }
}

$packt = new Packt();
$packt->packt();

在前面的代码中,当我们实例化类的对象时,调用了正常的__construct构造函数。packt()方法不被视为普通类方法。

旧式构造函数已被弃用,这意味着它们仍将在 PHP7 中工作,并将显示弃用的消息,但在即将发布的版本中将被删除。最好不要使用它们。

可丢弃接口

PHP7 引入了一个基接口,它可以作为可以使用throw语句的每个对象的基接口。在 PHP 中,可能会发生异常和错误。以前,可以处理异常,但不可能处理错误,因此,任何致命错误都会导致整个应用或应用的一部分停止。为了使错误(最致命的错误)也可捕获,PHP7 引入了可丢弃接口,该接口由异常和错误实现。

我们创建的 PHP 类无法实现 throwable 接口。如果需要,这些类必须扩展异常。

我们都知道异常,所以在本主题中,我们将只讨论错误,它可以处理丑陋、致命的错误。

错误

几乎所有致命错误现在都可以抛出错误实例,与异常类似,可以使用try/catch块捕获错误实例。让我们举一个简单的例子:

function iHaveError($object)
{
  return $object->iDontExist();
  {

//Call the function
iHaveError(null);
echo "I am still running";

如果执行前面的代码,将显示致命错误,应用将暂停,并且最终不会执行echo语句。

现在,我们将函数调用放在try/catch块中,如下所示:

try 
{
  iHaveError(null);
} catch(Error $e)
{
  //Either display the error message or log the error message
  echo $e->getMessage();
}

echo 'I am still running';

现在,如果执行前面的代码,catch主体将被执行,之后,应用的其余部分将继续运行。在前一种情况下,echo语句将被执行。

大多数情况下,对于最致命的错误会抛出错误实例,但对于某些错误,会抛出错误的子实例,如TypeErrorDivisionByZeroErrorParseError等。

现在,让我们来看看下面例子中的一个例外:

try
{
  $a = 20;
  $division = $a / 20;
} catch(DivisionByZeroError $e) 
{
  echo $e->getMessage();
}

在 PHP7 之前,前面的代码会发出关于除法为零的警告。但是,现在 PHP7 中的会抛出一个DivisionByZeroError,可以处理。

新运营商

PHP7 引入了两个感兴趣的操作符。这些运算符有助于编写更少、更干净的代码,因此与使用中的传统运算符相比,最终代码的可读性更高。我们来看看。

飞船操作员(<=>

Spaceship 或组合的比较运算符用于比较值(字符串、整数、浮点等)、数组和对象。该操作符只是一个包装器,执行与三个比较操作符==<>相同的任务。此运算符还可用于为usortuasortuksort的回调函数编写干净、更少的代码。该操作员的工作如下:

  • 如果左右两侧的操作数相等,则返回 0
  • 如果右操作数大于左操作数,则返回-1
  • 如果左操作数大于右操作数,则返回 1

让我们看看几个例子,通过比较整数、字符串、对象和数组,并注意结果:

$int1 = 1;
$int2 = 2;
$int3 = 1;

echo $int1 <=> $int3; //Returns 0
echo '<br>';
echo $int1 <=> $int2; //Returns -1
echo '<br>';
echo $int2 <=> $int3; //Returns 1

运行前面的代码,您将获得与以下类似的输出:

0
-1
1

在第一次比较中,我们比较了$int1$int3,两者相等,因此它将返回0。在第二次比较中,比较了$int1$int2,它将返回-1,因为右操作数($int2大于左操作数($int1。最后,第三次比较将返回1,因为左操作数($int2大于右操作数($int3

前面是一个比较整数的简单例子。我们可以用同样的方法检查字符串、对象和数组,并用同样的标准 PHP 方法对它们进行比较。

运算符的一些示例可在中找到 https://wiki.php.net/rfc/combined-comparison-operator 。这是一份 RFC 出版物,其中包含有关其用法的更有用的详细信息。

此运算符在排序数组时更有用。请看下面的代码:

Function normal_sort($a, $b) : int 
{
  if( $a == $b )
    return 0;
  if( $a < $b )
    return -1;
  return 1;
}

function space_sort($a, $b) : int
{
  return $a <=> $b;
}

$normalArray = [1,34,56,67,98,45];

//Sort the array in asc
usort($normalArray, 'normal_sort');

foreach($normalArray as $k => $v)
{
  echo $k.' => '.$v.'<br>';
}

$spaceArray = [1,34,56,67,98,45];

//Sort it by spaceship operator
usort($spaceArray, 'space_sort');

foreach($spaceArray as $key => $value)
{
  echo $key.' => '.$value.'<br>';
}

在前面的代码中,我们使用两个函数对具有相同值的两个不同数组进行排序。$normalArray数组按normal_sort函数排序,其中normal_sort函数使用if语句比较值。第二个数组$spaceArray的值与$normalArray值相同,但该数组是通过space_sort函数排序的,该函数使用 Spaceship 操作符。两个数组排序的最终结果相同,但回调函数中的代码不同。normal_sort函数有if语句和多行代码,space_sort函数只有一行代码,就是这样!space_sort功能代码更清晰,不需要多个 if 语句。

零联合算子(??)

我们都知道三元运算符,而且我们大部分时间都在使用它们。三元运算符只是if-else语句的单行替换。例如,考虑下面的代码:

$post = ($_POST['title']) ? $_POST['title'] : NULL;

如果$_POST['title']存在,则将$post变量赋值;否则,NULL将被分配。但是,如果$_POST$_POST['title']不存在或为空,则 PHP 将发出未定义索引的通知。要修复此通知,我们需要使用isset功能,如下所示:

$post = isset($_POST['title']) ? $_POST['title'] : NULL;

大多数情况下,这看起来很好,但当我们必须在多个位置检查值时,尤其是当使用 PHP 作为模板语言时,情况变得非常糟糕。

在 PHP7 中,引入了合并运算符,该运算符很简单,如果第一个操作数(左操作数)存在且不为空,则返回该操作数的值。否则,它将返回其第二个操作数(右操作数)。考虑下面的例子:

$post = $_POST['title'] ?? NULL;

此示例与前面的代码完全相似。合并操作符检查$_POST['title']是否存在。如果有,操作员将其返回;否则返回NULL

该操作符的另一个重要特性是它可以被链接。下面是一个例子:

$title = $_POST['title'] ?? $_GET['title'] ?? 'No POST or GET';

根据定义,首先检查第一个操作数是否存在并返回;如果不存在,它将返回第二个操作数。现在,如果在第二个操作数上使用了另一个合并运算符,则将应用相同的规则,如果左操作数上的值存在,将返回。否则,将返回右操作数的值。

因此,前面的代码与下面的代码相同:

If(isset($_POST['title']))
  $title = $_POST['title'];
elseif(isset($_GET['title']))
  $title = $_GET['title'];
else
  $title = 'No POST or GET';

正如前面的例子中所指出的,coalesce 操作符可以帮助编写干净、简洁和更少的代码。

统一变量语法

大多数情况下,我们可能会面临方法、变量或类名存储在其他变量中的情况。请看以下示例:

$objects['class']->name;

在前面的代码中,首先解释$objects['class'],然后解释属性名。如前一示例所示,变量通常从左到右求值。

现在,考虑下面的场景:

$first = ['name' => 'second'];
$second = 'Howdy';

echo $$first['name'];

在 PHP5.x 中,将执行此代码,输出为Howdy。但是,这与从左到右表达式的计算并不矛盾。这是因为$$first应该先求值,然后求值索引名,但在前一种情况下,求值为${$first['name']}。很明显,变量语法不一致,可能会造成混淆。为了避免这种不一致性,PHP7 引入了一种称为统一变量语法的新语法。如果不使用此语法,前面的示例将引起注意,并且不会产生期望的结果。要使其在 PHP 7 中工作,应添加花括号,如下所示:

echo ${$first['name']};

现在,让我们再举一个例子,如下所示:

class Packt
{
  public $title = 'PHP 7';
  public $publisher = 'Packt Publisher';

  public function getTitle() : string
  {
    return $this->title;
  }

  public function getPublisher() : string
  {
    return $this->publisher;
  }
}

$mthods = ['title' => 'getTitle', 'publisher' => 'getPublisher'];
$object = new Packt();
echo 'Book '.$object->$methods['title']().' is published by '.$object->$methods['publisher']();

如果前面的代码在 PHP5.x 中执行,它将正常工作并输出我们想要的结果。然而,如果我们在 PHP7 中执行此代码,它将给出一个致命错误。错误将出现在代码的最后一行,该行高亮显示。PHP7 将首先尝试评估 $object->$method.,然后尝试评估['title'];等等这是不对的。

要使其在 PHP7 中工作,应添加花括号,如以下代码所示:

echo 'Book '.$object->{$methods['title']}().' is published by '.$object->{$methods['publisher']}();

在进行前面提到的更改之后,我们将获得所需的输出。

其他特征和变化

PHP7 还引入了一些其他的新特性,只是做了一些小的改动,例如数组常量的新语法、switch语句中的多个默认情况、session_start中的选项数组等等。我们也来看看这些。

常数数组

从 PHP 5.6 开始,可以使用const关键字初始化常量数组,如下所示:

const STORES = ['en', 'fr', 'ar'];

现在,从 PHP 7 开始,可以使用define函数初始化常量数组,如下所示:

define('STORES', ['en', 'fr', 'ar']);

switch 语句中有多个默认情况

在 PHP7 之前,switch 语句中允许出现多个默认情况。请查看以下示例:

switch(true)
{
  default: 
    echo 'I am first one';
    break;
  default: 
    echo 'I am second one';
}

在 PHP 7 之前,前面的代码是允许的,但在 PHP 7 中,这将导致类似于以下内容的致命错误:

Fatal error: Switch statements may only contain one default clause in…

会话启动功能的选项数组

在 PHP7 之前,每当需要启动会话时,我们只需使用session_start()函数。此函数不带任何参数,使用了php.ini中定义的所有设置。现在,从 PHP7 开始,可以传递一个可选的选项数组,它将覆盖php.ini文件中的会话设置。

一个简单的例子如下:

session_start([
  'cookie_lifetime' => 3600,
  'read_and_close'  => true
]);

如前一示例所示,可以轻松覆盖会话的php.ini设置。

滤波非串行化功能

序列化和取消序列化对象是常见的做法。但是,PHPunserialize()函数不安全,因为它没有任何过滤选项,并且可以取消序列化任何类型的对象。PHP7 在这个函数中引入了过滤。默认筛选选项是取消序列化所有类或类型的对象。其基本工作如下:

$result = unserialize($object, ['allowed_classes' => ['Packt', 'Books', 'Ebooks']]);

总结

在本章中,我们讨论了新的 OOP 特性,例如类型提示、匿名类、可丢弃接口、名称空间的组使用声明,以及两个重要的新运算符,Spaceship 或 Combined 比较运算符和 null Coalesce 运算符。此外,我们还讨论了统一变量语法和其他一些新特性,例如联系人数组定义的新语法、session_start()函数的选项数组以及 switch 语句中多个默认情况的删除。

在下一章中,我们将讨论如何提高应用的性能。我们将讨论 Apache 和 NGINX 以及它们提高性能的不同设置。

我们将讨论 PHP 的不同设置,以提高其性能。还将讨论 Google 页面速度模块、CSS/JavaScript 组合和压缩、CDN 等。