PHP8.X各版本的新特性

发布时间:2024-03-26 01:55:57

PHP8.0新特性

1.命名参数

仅仅指定必填参数,跳过可选参数。

参数的顺序无关、自己就是文档(self-documented)

<?php

// PHP7
class Point {
  public float $x;
  public float $y;
  public float $z;

  public function __construct(
    float $x = 0.0,
    float $y = 0.0,
    float $z = 0.0
  ) {
    $this->x = $x;
    $this->y = $y;
    $this->z = $z;
  }
}

// PHP8
class Point {
  public function __construct(
    public float $x = 0.0,
    public float $y = 0.0,
    public float $z = 0.0,
  ) {}
}


2.注解

现在可以用 PHP 原生语法来使用结构化的元数据,而非 PHPDoc 声明。

<?php

// PHP7
class PostsController {
  /**
   * @Route("/api/posts/{id}", methods={"GET"})
   */
  public function get($id) { /* ... */}
}

// PHP8
class PostsController {
  #[Route("/api/posts/{id}", methods: ["GET"])]
  public function get($id) { /* ... */}
}


3.构造器属性提升

更少的样板代码来定义并初始化属性。

<?php

// PHP7
class Point {
  public float $x;
  public float $y;
  public float $z;
  public function __construct(
    float $x = 0.0,
    float $y = 0.0,
    float $z = 0.0,
  ) {
    $this->x = $x;
    $this->y = $y;
    $this->z = $z;
  }
}

// PHP8
class Point {
  public function __construct(
    public float $x = 0.0,
    public float $y = 0.0,
    public float $z = 0.0,
  ) {}
}


4.联合类型

相对于以前的 PHPDoc 声明类型的组合, 现在可以用原生支持的联合类型声明取而代之,可在实际运行中验证。

<?php

// PHP7
class Number {
  /** @var int|float */
  private $number;
  /**
   * @param float|int $number
   */
  public function __construct($number) {
    $this->number = $number;
  }
}
new Number('NaN'); // Ok

// PHP8
class Number {
  public function __construct(
    private int | float $number
  ) {}
}
new Number('NaN'); // TypeError


5.Match 表达式

新的 match 类似于 switch,并具有以下功能:

Match 是一个表达式,它可以储存到变量中亦可以直接返回。

Match 分支仅支持单行,它不需要一个 break; 语句。

Match 使用严格比较。

<?php

// PHP7
switch (8.0) {
case '8.0':
  $result = "Oh no!";
  break;
case 8.0:
  $result = "This is what I expected";
  break;
}
echo $result;
//输出: Oh no!

// PHP8
echo match (8.0) {
  '8.0' => "Oh no!",
  8.0 => "This is what I expected",
};
//输出: This is what I expected


6.Nullsafe 运算符

现在可以用新的 nullsafe 运算符链式调用,而不需要条件检查 null。 如果链条中的一个元素失败了,整个链条会中止并认定为 Null。

<?php

// PHP7
$country = null;
if ($session !== null) {
  $user = $session->user;
  if ($user !== null) {
    $address = $user->getAddress();

    if ($address !== null) {
      $country = $address->country;
    }
  }
}

// PHP8
$country = $session?->user?->getAddress()?->country;


7.字符串与数字的比较更符合逻辑

PHP 8 比较数字字符串(numeric string)时,会按数字进行比较。 不是数字字符串时,将数字转化为字符串,按字符串比较。

<?php

// PHP7
0 == 'foobar' // true

// PHP8
0 == 'foobar' // false


8.内部函数类型错误的一致性

现在大多数内部函数在参数验证失败时抛出 Error 级异常。

<?php

// PHP7
strlen([]); // Warning: strlen() expects parameter 1 to be string, array given
array_chunk([], -1); // Warning: array_chunk(): Size parameter expected to be greater than 0

// PHP8
strlen([]); // TypeError: strlen(): Argument #1 ($str) must be of type string, array given
array_chunk([], -1); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0


9.即时编译

PHP 8 引入了两个即时编译引擎。 Tracing JIT 在两个中更有潜力,它在综合基准测试中显示了三倍的性能, 并在某些长时间运行的程序中显示了 1.5-2 倍的性能改进。 典型的应用性能则和 PHP 7.4 不相上下。



10.类型系统与错误处理的改进

算术/位运算符更严格的类型检测

Abstract trait 方法的验证

确保魔术方法签名正确

PHP 引擎 warning 警告的重新分类

不兼容的方法签名导致 Fatal 错误

操作符 @ 不再抑制 fatal 错误。

私有方法继承

Mixed 类型

Static 返回类型

内部函数的类型 Email thread

扩展 Curl、 Gd、 Sockets、 OpenSSL、 XMLWriter、 XML 以 Opaque 对象替换 resource。


11.其他语法调整和改进

允许参数列表中的末尾逗号、 闭包 use 列表中的末尾逗号

无捕获的 catche

变量语法的调整

Namespace 名称作为单个 token

现在 throw 是一个表达式

允许对象的 ::class


12.新的类、接口、函数

Weak Map 类

Stringable 接口

str_contains()、 str_starts_with()、 str_ends_with()

fdiv()

get_debug_type()

get_resource_id()

token_get_all() 对象实现


PHP8.1新特性

1.枚举

使用枚举而不是一组常量并立即进行验证。

<?php

// PHP < 8.1
class Status
{
  const DRAFT = 'draft';
  const PUBLISHED = 'published';
  const ARCHIVED = 'archived';
}
function acceptStatus(string $status) {...}

// PHP 8.1
enum Status
{
  case Draft;
  case Published;
  case Archived;
}
function acceptStatus(Status $status) {...}


2.只读属性

只读属性不能在初始化后更改,即在为它们分配值后。它们可以用于对值对象和数据传输对象建模。

<?php

// PHP < 8.1
class BlogData {
  private Status $status;

  public function __construct(Status $status) {
    $this->status = $status;
  }

  public function getStatus(): Status {
    return $this->status;
  }
}

// PHP 8.1
class BlogData {
  public readonly Status $status;

  public function __construct(Status $status) {
    $this->status = $status;
  }
}


3.First-class 可调用语法

现在可以获得对任何函数的引用。这统称为 First-class 可调用语法。

<?php

// PHP < 8.1
$foo = [$this, 'foo'];
$fn = Closure::fromCallable('strlen');

// PHP 8.1
$foo = $this->foo(...);
$fn = strlen(...);


4.新的初始化器

对象现在可以用作默认参数值、静态变量和全局常量,以及属性参数。

这有效地使使用 嵌套属性 成为可能。

<?php

// PHP < 8.1
class Service {
  private Logger $logger;

  public function __construct(
    ?Logger $logger = null,
  ) {
    $this->logger = $logger ?? new NullLogger();
  }
}

// PHP 8.1
class Service {
  private Logger $logger;

  public function __construct(
    Logger $logger = new NullLogger(),
  ) {
    $this->logger = $logger;
  }
}
<?php

// PHP < 8.1
class User {
  /**
   * @Assert\All({
   *     @Assert\NotNull,
   *     @Assert\Length(min=5)
   * })
   */
  public string $name = '';
}

// PHP 8.1
class User {
  #[\Assert\All(
    new \Assert\NotNull,
    new \Assert\Length(min: 5))
]
  public string $name = '';
}


5.纯交集类型

当一个值需要同时满足多个类型约束时,使用交集类型。

注意,目前无法将交集和联合类型混合在一起,例如 A&B|C。

<?php

// PHP < 8.1
function count_and_iterate(Iterator $value) {
  if (!($value instanceof Countable)) {
    throw new TypeError('value must be Countable');
  }

  foreach ($value as $val) {
    echo $val;
  }

  count($value);
}

// PHP 8.1
function count_and_iterate(Iterator&Countable $value) {
  foreach ($value as $val) {
    echo $val;
  }

  count($value);
}


6.Never 返回类型

使用 never 类型声明的函数或方法表示它不会返回值,并且会抛出异常或通过调用 die()、exit()、trigger_error() 或类似的东西来结束脚本的执行。

<?php

// PHP < 8.1
function redirect(string $uri) {
  header('Location: ' . $uri);
  exit();
}

function redirectToLoginPage() {
  redirect('/login');
  echo 'Hello'; // <- dead code
}

// PHP 8.1
function redirect(string $uri): never {
  header('Location: ' . $uri);
  exit();
}

function redirectToLoginPage(): never {
  redirect('/login');
  echo 'Hello'; // <- dead code detected by static analysis 
}


7.Final 类常量

可以声明 final 类常量,以禁止它们在子类中被重写。

<?php

// PHP < 8.1
class Foo
{
  public const XX = "foo";
}

class Bar extends Foo
{
  public const XX = "bar"; // No error
}

// PHP 8.1
class Foo
{
  final public const XX = "foo";
}

class Bar extends Foo
{
  public const XX = "bar"; // Fatal error
}


8.显式八进制数字表示法

现在可以使用显式 0o 前缀表示八进制数。

<?php

// PHP < 8.1
016 === 16; // false because `016` is octal for `14` and it's confusing
016 === 14; // true 

// PHP 8.1
0o16 === 16; // false — not confusing with explicit notation
0o16 === 14; // true


9.纤程

Fibers 是用于实现轻量级协作并发的基础类型。它们是一种创建可以像生成器一样暂停和恢复的代码块的方法,但可以从堆栈中的任何位置进行。Fibers 本身并没有提供并发性,仍然需要一个事件循环。但是,它们允许通过阻塞和非阻塞实现共享相同的 API。


Fibers 允许摆脱以前在 Promise::then() 或基于生成器的协程中看到的样板代码。库通常会围绕 Fiber 构建进一步的抽象,因此无需直接与它们交互。

<?php

// PHP < 8.1
$httpClient->request('https://example.com/')
  ->then(function (Response $response) {
    return $response->getBody()->buffer();
  })
  ->then(function (string $responseBody) {
    print json_decode($responseBody)['code'];
  });

// PHP 8.1
$response = $httpClient->request('https://example.com/');
print json_decode($response->getBody()->buffer())['code'];


10.对字符串键控数组的数组解包支持

PHP 以前支持通过扩展运算符在数组内部解包,但前提是数组具有整数键。现在也可以使用字符串键解包数组。

<?php

// PHP < 8.1
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];
$result = array_merge(['a' => 0], $arrayA, $arrayB);
// ['a' => 1, 'b' => 2]

// PHP 8.1
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];
$result = ['a' => 0, ...$arrayA, ...$arrayB];
// ['a' => 1, 'b' => 2]


11.性能改进

结果(相对于 PHP 8.0):

Symfony Demo 有 23.0% 的提升

WordPress 有 3.5% 的提升

PHP 8.1 中与性能相关的特性:

ARM64 的 JIT 后端 (AArch64)

继承缓存(避免在每个请求中重新链接类)

快速解析类名(避免小写和哈希查找)

timelib 和 ext/date 性能改进

SPL 文件系统迭代器改进

serialize/unserialize 优化

一些内部函数优化(get_declared_classes()、explode()、strtr()、strnatcmp() 和 dechex())

JIT 的改进和修复


12.新的类、接口和函数

#[ReturnTypeWillChange] 属性。

fsync 和 fdatasync 函数。

array_is_list 函数。

Sodium XChaCha20 函数。


13.弃用和向后不兼容

向非空值的内部函数参数传递空值的做法已被弃用。

PHP 内置类方法中的暂定返回类型

Serializable 接口已弃用。

html_entity_encode/html_entity_decode 函数默认处理单引号和用 Unicode 替换字符来替换无效字符。

$GLOBALS 变量限制。

MySQLi:默认错误模式设置为异常。

隐式不兼容的 float 到 int 转换已被弃用。

finfo 扩展:file_info 资源迁移到现有的 finfo 对象。

IMAP:imap 资源迁移到 IMAP\Connection 类对象。

FTP 扩展:连接资源迁移到 FTP\Connection 类对象。

GD 扩展:字体标识符迁移到 GdFont 类对象。

LDAP:资源类型迁移到 LDAP\Connection、LDAP\Result 和 LDAP\ResultEntry 对象。

PostgreSQL:资源类型迁移到 PgSql\Connection、PgSql\Result 和 PgSql\Lob 对象。

Pspell:pspell 和 pspell config 资源类型迁移到 PSpell\Dictionary、PSpell\Config 类对象。


PHP8.2新特性

1.只读类

<?php

// PHP < 8.2
class BlogData
{
  public readonly string $title;
  public readonly Status $status;

  public function __construct(string $title, Status $status)
  {
    $this->title = $title;
    $this->status = $status;
  }
}

// PHP 8.2
readonly class BlogData
{
  public string $title;
  public Status $status;

  public function __construct(string $title, Status $status)
  {
    $this->title = $title;
    $this->status = $status;
  }
}


2.析取范式 (DNF)类型

DNF 类型允许我们组合 union 和 intersection类型,遵循一个严格规则:组合并集和交集类型时,交集类型必须用括号进行分组。

<?php

// PHP < 8.2
class Foo {
  public function bar(mixed $entity) {
    if ((($entity instanceof A) && ($entity instanceof B)) || ($entity === null)) {
      return $entity;
    }

    throw new Exception('Invalid entity');
  }
}

// PHP 8.2
class Foo {
  public function bar((A&B) | null $entity) {
    return $entity;
  }
}


3.允许 null、false 和 true 作为独立类型

<?php

// PHP < 8.2
class Falsy
{
  public function almostFalse(): bool { /* ... */ *}

  public function almostTrue(): bool { /* ... */ *}

  public function almostNull(): string|null { /* ... */ *}
}

// PHP 8.2
class Falsy
{
  public function alwaysFalse(): false { /* ... */ *}

  public function alwaysTrue(): true { /* ... */ *}

  public function alwaysNull(): null { /* ... */ *}
}


4.新的“随机”扩展

“随机”扩展为随机数生成提供了一个新的面向对象的 API。这个面向对象的 API 提供了几个类(“引擎”),提供对现代算法的访问,这些算法在对象中存储其状态,以允许多个独立的可播种序列,而不是依赖于使用 Mersenne Twister 算法的全局种子随机数发生器(RNG)。


\Random\Randomizer 类提供了一个高级接口来使用引擎的随机性来生成随机整数、随机排列数组或字符串、选择随机数组键等。

<?php

use Random\Engine\Xoshiro256StarStar;
use Random\Randomizer;

$blueprintRng = new Xoshiro256StarStar(
  hash('sha256', "Example seed that is converted to a 256 Bit string via SHA-256", true)
);

$fibers = [];
for ($i = 0; $i < 8; $i++) {
  $fiberRng = clone $blueprintRng;
  // Xoshiro256**'s 'jump()' method moves the blueprint ahead 2**128 steps, as if calling
  // 'generate()' 2**128 times, giving the Fiber 2**128 unique values without needing to reseed.
  $blueprintRng->jump();

  $fibers[] = new Fiber(function () use ($fiberRng, $i): void {
    $randomizer = new Randomizer($fiberRng);

    echo "{$i}: " . $randomizer->getInt(0, 100), PHP_EOL;
  });
}

// The randomizer will use a CSPRNG by default.
$randomizer = new Randomizer();

// Even though the fibers execute in a random order, they will print the same value
// each time, because each has its own unique instance of the RNG.
$fibers = $randomizer->shuffleArray($fibers);
foreach ($fibers as $fiber) {
  $fiber->start();
}


5.Traits 中的常量

您不能通过 trait 名称访问常量,但是您可以通过使用 trait 的类访问常量。

<?php

trait Foo
{
  public const CONSTANT = 1;
}

class Bar
{
  use Foo;
}

var_dump(Bar::CONSTANT); // 1
var_dump(Foo::CONSTANT); // Error


6.弃用动态属性

动态属性的创建已被弃用,以帮助避免错误和拼写错误,除非该类通过使用 #[\AllowDynamicProperties] 属性来选择。stdClass 允许动态属性。


__get/__set 魔术方法的使用不受此更改的影响。

<?php

// PHP < 8.2
class User
{
  public $name;
}

$user = new User();
$user->last_name = 'Doe';

$user = new stdClass();
$user->last_name = 'Doe';

// PHP 8.2
class User
{
  public $name;
}

$user = new User();
$user->last_name = 'Doe'; // Deprecated notice

$user = new stdClass();
$user->last_name = 'Doe'; // Still allowed


7.新的类、接口和函数

新增 mysqli_execute_query 函数和 mysqli::execute_query 方法。

新增 #[\AllowDynamicProperties] 和 #[\SensitiveParameter] 属性。

新增 ZipArchive::getStreamIndex、ZipArchive::getStreamName 和 ZipArchive::clearError 方法。

新增 ReflectionFunction::isAnonymous 和 ReflectionMethod::hasPrototype 方法。

新增 curl_upkeep、memory_reset_peak_usage、ini_parse_quantity、libxml_get_external_entity_loader、sodium_crypto_stream_xchacha20_xor_ic 和 openssl_cipher_key_length 方法。


8.弃用和向后不兼容

弃用 ${} 字符串插值。

弃用 utf8_encode 和 utf8_decode 函数。

DateTime::createFromImmutable 和 DateTimeImmutable::createFromMutable 方法暂定返回类型为 static。

ODBC 和 PDO_ODBC 扩展转义用户名和密码。

strtolower 和 strtoupper 函数不再对语言环境敏感。

SplFileObject::getCsvControl、SplFileObject::fflush、SplFileObject::ftell、SplFileObject::fgetc 和 SplFileObject::fpassthru 方法强制执行它们的签名。

SplFileObject::hasChildren 方法暂定返回类型为 false。

SplFileObject::getChildren 方法暂定返回类型为 null。

内置方法 SplFileInfo::_bad_state_ex 已被废弃。


PHP8.3新特性

1.类型化类常量

<?php

// PHP < 8.3
interface I {
  // We may naively assume that the PHP constant is always a string.
  const PHP = 'PHP 8.2';
}

class Foo implements I {
  // But implementing classes may define it as an array.
  const PHP = [];
}

// PHP 8.3
interface I {
  const string PHP = 'PHP 8.3';
}

class Foo implements I {
  const string PHP = [];
}

// Fatal error: Cannot use array as value for class constant
// Foo::PHP of type string


2.动态获取类常量

<?php

// PHP < 8.3
class Foo {
  const PHP = 'PHP 8.2';
}

$searchableConstant = 'PHP';

var_dump(constant(Foo::class . "::{$searchableConstant}"));

// PHP 8.3
class Foo {
  const PHP = 'PHP 8.3';
}

$searchableConstant = 'PHP';

var_dump(Foo::{$searchableConstant});


3.新增 #[\Override] 属性

通过给方法添加 #[\Override] 属性,PHP 将确保在父类或实现的接口中存在同名的方法。添加该属性表示明确说明覆盖父方法是有意为之,并且简化了重构过程,因为删除被覆盖的父方法将被检测出来。

<?php

// PHP < 8.3
use PHPUnit\Framework\TestCase;

final class MyTest extends TestCase {
  protected $logFile;

  protected function setUp(): void {
    $this->logFile = fopen('/tmp/logfile', 'w');
  }

  protected function taerDown(): void {
    fclose($this->logFile);
    unlink('/tmp/logfile');
  }
}

// The log file will never be removed, because the
// method name was mistyped (taerDown vs tearDown).

// PHP 8.3
use PHPUnit\Framework\TestCase;

final class MyTest extends TestCase {
  protected $logFile;

  protected function setUp(): void {
    $this->logFile = fopen('/tmp/logfile', 'w');
  }

  #[\Override]
  protected function taerDown(): void {
    fclose($this->logFile);
    unlink('/tmp/logfile');
  }
}

// Fatal error: MyTest::taerDown() has #[\Override] attribute,
// but no matching parent method exists


4.只读属性深拷贝

readonly 属性现在可以在魔术方法 __clone 中被修改一次,以此实现只读属性的深拷贝

<?php

// PHP < 8.3
class PHP {
  public string $version = '8.2';
}

readonly class Foo {
  public function __construct(
    public PHP $php
  ) {}

  public function __clone(): void {
    $this->php = clone $this->php;
  }
}

$instance = new Foo(new PHP());
$cloned = clone $instance;

// Fatal error: Cannot modify readonly property Foo::$php

// PHP 8.3
class PHP {
  public string $version = '8.2';
}

readonly class Foo {
  public function __construct(
    public PHP $php
  ) {}

  public function __clone(): void {
    $this->php = clone $this->php;
  }
}

$instance = new Foo(new PHP());
$cloned = clone $instance;

$cloned->php->version = '8.3';


5.新增 json_validate() 函数

json_validate() 可以检查一个字符串是否为语法正确的 JSON,比 json_decode() 更有效。

<?php

// PHP < 8.3
function json_validate(string $string): bool {
  json_decode($string);

  return json_last_error() === JSON_ERROR_NONE;
}

var_dump(json_validate('{ "test": { "foo": "bar" } }')); // true

// PHP 8.3
var_dump(json_validate('{ "test": { "foo": "bar" } }')); // true


6.新增 Randomizer::getBytesFromString() 方法

在 PHP 8.2 中新增的 Random 扩展 通过一个新方法生成由特定字节组成的随机字符串。这种方法可以使开发者更轻松的生成随机的标识符(如域名),以及任意长度的数字字符串。

<?php

// PHP < 8.3
// This function needs to be manually implemented.
function getBytesFromString(string $string, int $length) {
  $stringLength = strlen($string);

  $result = '';
  for ($i = 0; $i < $length; $i++) {
    // random_int is not seedable for testing, but secure.
    $result .= $string[random_int(0, $stringLength - 1)];
  }

  return $result;
}

$randomDomain = sprintf(
  "%s.example.com",
  getBytesFromString(
    'abcdefghijklmnopqrstuvwxyz0123456789',
    16,
  ),
);

echo $randomDomain;

// PHP 8.3
// A \Random\Engine may be passed for seeding,
// the default is the secure engine.
$randomizer = new \Random\Randomizer();

$randomDomain = sprintf(
  "%s.example.com",
  $randomizer->getBytesFromString(
    'abcdefghijklmnopqrstuvwxyz0123456789',
    16,
  ),
);

echo $randomDomain;


7.新增 Randomizer::getFloat() 和 Randomizer::nextFloat() 方法

由于浮点数的精度和隐式四舍五入的限制,在特定区间内生成无偏差的浮点数并非易事,常建的用户解决方案可能会生成有偏差的结果或超出要求范围的数字。


Randomizer 扩展了两种方法,用于随机生成无偏差的浮点数。Randomizer::getFloat() 方法使用的是 γ-section 算法,该算法发表于 Drawing Random Floating-Point Numbers from an Interval. Frédéric Goualard, ACM Trans. Model. Comput. Simul., 32:3, 2022.

<?php

// PHP < 8.3
// Returns a random float between $min and $max, both including.
function getFloat(float $min, float $max) {
  // This algorithm is biased for specific inputs and may
  // return values outside the given range. This is impossible
  // to work around in userland.
  $offset = random_int(0, PHP_INT_MAX) / PHP_INT_MAX;

  return $offset * ($max - $min) + $min;
}

$temperature = getFloat(-89.2, 56.7);

$chanceForTrue = 0.1;
// getFloat(0, 1) might return the upper bound, i.e. 1,
// introducing a small bias.
$myBoolean = getFloat(0, 1) < $chanceForTrue;

// PHP 8.3
$randomizer = new \Random\Randomizer();

$temperature = $randomizer->getFloat(
  -89.2,
  56.7,
  \Random\IntervalBoundary::ClosedClosed,
);

$chanceForTrue = 0.1;
// Randomizer::nextFloat() is equivalent to
// Randomizer::getFloat(0, 1, \Random\IntervalBoundary::ClosedOpen).
// The upper bound, i.e. 1, will not be returned.
$myBoolean = $randomizer->nextFloat() < $chanceForTrue;


8.命令行 linter 支持多个文件

命令行 linter 现在接受文件名的可变输入以进行 lint

// PHP < 8.3
php -l foo.php bar.php
No syntax errors detected in foo.php

// PHP 8.3
php -l foo.php bar.php
No syntax errors detected in foo.php
No syntax errors detected in bar.php


9.新的类、接口和函数

新增 DOMElement::getAttributeNames()、DOMElement::insertAdjacentElement()、DOMElement::insertAdjacentText()、DOMElement::toggleAttribute()、DOMNode::contains()、DOMNode::getRootNode()、DOMNode::isEqualNode()、DOMNameSpaceNode::contains() 和 DOMParentNode::replaceChildren() 方法。

新增 IntlCalendar::setDate()、IntlCalendar::setDateTime()、IntlGregorianCalendar::createFromDate() 和 IntlGregorianCalendar::createFromDateTime() 方法。

新增 ldap_connect_wallet() 和 ldap_exop_sync() 函数。

新增 mb_str_pad() 函数。

新增 posix_sysconf()、posix_pathconf()、posix_fpathconf() 和 posix_eaccess() 函数。

新增 ReflectionMethod::createFromMethodName() 方法

新增 socket_atmark() 函数。

新增 str_increment()、str_decrement() 和 stream_context_set_options() 函数。

新增 ZipArchive::getArchiveFlag() 方法。

支持在 OpenSSL 扩展中使用自定义 EC 参数生成 EC 密钥。

新增 INI 设置 zend.max_allowed_stack_size 用于设置允许的最大堆栈大小。

php.ini 现在支持后备/默认值语法。

匿名类现在可以是只读的。


10.弃用和向后不兼容

更合适的 Date/Time 异常。

现在在空数组中获取负索引 n 时,将确保下一个索引是 n + 1 而不是 0。

对 range() 函数的更改。

在 traits 中重新声明静态属性的更改。

U_MULTIPLE_DECIMAL_SEPERATORS 常量已被废弃,改为 U_MULTIPLE_DECIMAL_SEPARATORS。

MT_RAND_PHP Mt19937 变体已被废弃。

ReflectionClass::getStaticProperties() 不再为空。

INI 配置 assert.active、assert.bail、assert.callback、assert.exception 和 assert.warning 已被废弃。

调用 get_class() 和 get_parent_class() 时未提供参数,已被废弃。

SQLite3:默认错误模式设置为异常。