文档结构  
可译网翻译有奖活动正在进行中,查看详情 现在前往 注册?
原作者:未知 (2016-12-08)    来源:SitePoint [英文]
中山狼    计算机    2016-12-10    0评/444阅
翻译进度:75%   参与翻译: CY2 (6), itsmikej (2), 中山狼 (1)

PHP 社区刚刚发布了最新的 PHP 7.1 版本,该版本在语言方面带来了诸多新特性。本文向你介绍其中最重要的一些新特性介绍,更详细的列表可阅读 PHP RFC

Flying baloon-tied elephpant

ArgumentCountError 异常

早期的 PHP 版本允许函数调用时,传递的参数少于函数定义本身要求的参数个数。当你调用函数时就会抛出一个参数丢失的警告。

// PHP 5.6

function sum($a, $b)
{
    return $a + $b;
}

sum(); 
// Warning: Missing argument 1 for sum()
// Warning: Missing argument 2 for sum()

sum(3);
// Warning: Missing argument 2 for sum()

sum(3, 4);
第 1 段(可获 0.94 积分)

在这种情况下警告没什么用,开发者必须自行检查参数是否正确。在 PHP 7.1 中,这些警告变成了一个 ArgumentCountError 的异常:

// PHP 7.1

function sum($a, $b)
{
    return $a + $b;
}

sum(); 
// Fatal error: Uncaught ArgumentCountError: Too few arguments to function sum(), 0 passed in /vagrant/index.php on line 18 and exactly 2 expected in /vagrant/index.php:13

sum(3); // skipped

sum(3, 4); // skipped 

可空类型 Nullable Types

PHP 7 增加了参数和返回值的类型定义,但是似乎还少了点什么。而 Nullable 类型可以指定类型或者为空,例如:

第 2 段(可获 0.84 积分)
function sum(int $a, int $b): ?int
{
    return $a + $b;
}

上述函数中将返回一个整数或者是空值,如果函数逻辑发生错误,你将不会返回错误类型的空值。函数的参数也可以这么玩:

function sum(?int $a, ?int $b): ?int
{
    if ($a == null || $b == null) {
        return null;
    }

    return $a + $b;
}

一种不在预期的情况是当调用此函数并不传递任意参数时将会抛出异常!

var_dump(sum(null, null)); // NULL
var_dump(sum()); // throw ArgumentCountError exception
第 3 段(可获 0.66 积分)

这意味着你必须显式的指定参数值,因为这些参数没有默认值。

你还需要记住另外一种情况是,当重写或者实现方法时,返回对象类型不能是允许为空的类型,但你可以删掉它。而参数则刚好相反,你不能删除参数中允许为空的类型,但允许添加!

interface Fooable {
    function foo(): ?Fooable;
}
interface StrictFooable extends Fooable {
    function foo(): Fooable; // valid
}

interface Fooable {
    function foo(): Fooable;
}
interface LooseFooable extends Fooable {
    function foo(): ?Fooable; // invalid
}
第 4 段(可获 0.89 积分)

Destructuring Arrays

We used to do the following when destructuring arrays.

list($a, $b, $c) = [1, 2, 3];
var_dump($a, $b, $c); // int(1) int(2) int(3)

But trying this would fail, because we couldn’t specify keys to extract and the function tried to use index keys.

list($a, $b, $c) = ["a" => 1, "b" => 2, "c" => 3];
var_dump($a, $b, $c); // NULL NULL NULL

This RFC provides more control over array destructuring. The above code could be changed to this.

list("a" => $a, "b" => $b, "c" => $c) = ["a" => 1, "b" => 2, "c" => 3];
var_dump($a, $b, $c); // int(1) int(2) int(3)
第 5 段(可获 0.6 积分)

The list function now accepts keys for array destructuring, and because this is used a lot, a new compact syntax has been introduced. Take this as an example.

["a" => $a, "b" => $b, "c" => $c] = ["a" => 1, "b" => 2, "c" => 3];
var_dump($a, $b, $c); // int(1) int(2) int(3)

Cool, isn’t it? And it also works on multidimensional arrays.

[[$a, $b], [$c, $d]] = [[1, 2], [3, 4]];
var_dump($a, $b, $c, $d); // int(1) int(2) int(3) int(4)

[["b" => $b], ["c" => $c]] = [["a" => 1, "b" => 2], ["c" => 3, "d" => 4]];
var_dump($b, $c); // int(2) int(3)

Iterable Type

第 6 段(可获 0.5 积分)

The iterable pseudo-type is added to join the array primitive type and the Traversable interface which is used to make a value iterable. Take the below code as an example.

// PHP 5.6

function dump(array $items)
{
    var_dump($items);
}

dump([2, 3, 4]);
dump(new Collection());
array(3) {
  [0]=>
  int(2)
  [1]=>
  int(3)
  [2]=>
  int(4)
}

Catchable fatal error: Argument 1 passed to dump() must be of the type array, object given...

But in this case, the function won’t accept an iterable value and will throw an error. This new change lets you use iterable to describe an iterable value instead of asserting it manually.

第 7 段(可获 0.76 积分)
// PHP 7.1

function dump(iterable $items)
{
    var_dump($items);
}

dump([2, 3, 4]);
dump(new Collection());
array(3) {
  [0]=>
  int(2)
  [1]=>
  int(3)
  [2]=>
  int(4)
}
object(Collection)#2 (0) {
}

Closure FromCallable 函数

新的 fromCallable 方法提供一个高效和简洁的方式来创建闭包。请看下面的案例:

$callback = Closure::fromCallable([$this, 'fn']);

Void 返回类型

这是我最爱的特性之一, 它完善了 PHP7 中的返回类型特性,之前如果函数没有返回的话,我们只能强制添加上 return null。

第 8 段(可获 0.73 积分)
function dump($object): void
{
    var_dump($object);
}

返回值为 void 的函数会忽略函数体中的 return 语句或者是增加一个空的返回语句 return ;。

类常量的可见性

这是一个小的变化。但却是面向对象编程中重要的一部分 —— 封装增强。为类的常量增加了可见性的修饰符。

class Post
{
    protected const PUBLISHED = 1;
    protected const DRAFT = 2;
    protected const TRASHED = 3;

    // ...
}

捕获多个异常类型

类似 Java 等其他语言都提供了在同一个 catch 块代码中同事捕获多个异常的做法,这样可以避免不必要的代码重复。请看以下例子:

第 9 段(可获 0.9 积分)
// ...

try {
    $user->payMonth($month);
} catch (UserSuspendedException $ex) {
    DB::rollBack();

    return redirect()
            ->back()
            ->withInput()
            ->withErrors([$ex->getMessage()]);
} catch (PaidMonthException $e) {
    DB::rollBack();

    return redirect()
            ->back()
            ->withInput()
            ->withErrors([$ex->getMessage()]);
}

// ...

你可以通过全新的 catch 块语法来移除重复代码:

// ...

try {
    $user->payMonth($month);
} catch (PaidMonthException | UserSuspendedException $ex) {
    DB::rollBack();

    return redirect()
            ->back()
            ->withInput()
            ->withErrors([$ex->getMessage()]);
}

// ...
第 10 段(可获 0.15 积分)

无效的字符串算法

当你开始学习 PHP 时,在做算术计算时你可能会感到惊喜,因为你知道字符串也可以用来做运算。这是因为 PHP 适合 Web 编程,总是把很多值当成字符串来处理。

// PHP 5.6

var_dump("1" + "2");
var_dump("1" + "a string");
var_dump("1" + "2  with a string");
int(3)
int(1)
int(3)
// PHP 7.1

var_dump("1" + "2");
var_dump("1" + "a string");
var_dump("1" + "2  with a string");
int(3)

Warning: A non-numeric value encountered in /vagrant/index.php on line 17
int(1)

Notice: A non well formed numeric value encountered in /vagrant/index.php on line 18
int(3)
第 11 段(可获 0.49 积分)

非数值类型的值相加会抛出一个 Warning, 未格式化的值相加会抛出一个 Notice (2 a string = 2)。

结语

这篇文章没有覆盖所有的新特性, 完整的变动可以在这里找到 RFC list。 如果你有任何关于 PHP7.1 特性或者是 PHP 的相关问题,请再下面留言。

第 12 段(可获 0.83 积分)

文章评论