PHP头条
热点:

PHP 7 新特性,php新特性


转载自:

https://zhuanlan.zhihu.com/p/27694633

https://zhuanlan.zhihu.com/p/27847880

https://zhuanlan.zhihu.com/p/29478077

https://goghcrow.gitbooks.io/php7/content/xin-te-xing.html

PHP 7 之前的类型提示

PHP 5.0 首次提出函数参数(只针对对象类型)的类型提示(Type Hint),之后 PHP 5.1 进一步扩展到可针对数组类型。举例如下:

<?php
class Person
{
    public $name;
    public $id;
    function __construct($name, $id) {
        $this->name = $name;
        $this->id = $id;
    }
}

$person = new Person("Tom", 101);

function printPerson(Person $person) {
    echo "Name: ", $person->name, ", ID: ", $person->id, ".";
}

printPerson($person);

$skills = ["PHP 7", "C++", "Java", "Golang", "Python"];  // PHP 5.4 起可以使用数组定义短语法

function printSkills(array $skills) {
    foreach ($skills as $skill) {
        echo $skill, "\n";
    }
}

printSkills($skills);

运行结果如下图所示:

而时光到了 PHP 7,类型提示的增强则更进了一步。

PHP 7 的标量参数类型提示

PHP 7 增加了对标量参数类型的支持:

  • int
  • float
  • string
  • bool

举例如下:

// Scalar Type Hints
function printRecord(string $name, int $id, float $salary, bool $sex) {
    echo $sex ? "$name, $id, $salary, male." : "$name, $id, $salary, female.";
}

printRecord("Tom", 101, 5650.00, TRUE);
printRecord("Suzy", 101, 5650.00, FALSE);

运行结果如下图所示:

PHP 7 的函数/方法返回值类型提示

PHP 7还支持了函数/方法返回值类型提示。举例如下:

function getRecord(string $name, int $id, float $salary, bool $sex) : string {
    return $sex ? "$name, $id, $salary, male." : "$name, $id, $salary, female.";
}

getRecord("Tom", 101, 5650.00, TRUE);

结果如下图所示:

return的返回类型提示,跟 PHPDoc 的 @return 注解是完全不同的两个方面,@return 只是“好言规劝”或向IDE“友好反馈”返回类型应该是什么,而对于实际的返回类型不具约束力。return的返回类型提示则具有对返回类型的运行时强制约束力——具体有待后续进一步阐述,稍安勿躁。

类型提示特性中其他一些问题点

如果函数参数或返回值是对象咋办呢?进一步来说,类型提示涉及父类继承或接口实现时,又是怎样一种表现呢?让我们继续前进的脚步吧。

interface iFoo {}
class Foo implements iFoo {}
class Bar extends Foo {}

function coo(iFoo $foo) : iFoo {
    return $foo;
}

coo(new Foo());
coo(new Bar());

function gaa(Foo $foo) : iFoo {
    return $foo;
}

gaa(new Foo());
gaa(new Bar());

function zii(Bar $bar) : Foo {
    return $bar;
}

zii(new Foo());  // TypeError: Argument 1 passed to zii() must be an instance of Bar, instance of Foo given on line 1
zii(new Bar());

综上,上代码看得最清楚,不太想多花笔墨了。

严格类型约束

还有一个很重要的特性——严格类型约束——declare(strict_types=1);

不妨来看看:

function xii(array $a, string $s) : int {
    print_r($a);
    echo $s, "\n";
    return "101";
}

xii([1, 2, 3, 4, 5, 6, 7, 8], 101);
xii(101, 102);  // TypeError: Argument 1 passed to xii() must be of the type array, integer given on line 1

对于标量类型提示,我们的参数也罢、返回值也罢,其类型跟类型提示不一致也不影响程序运行(注:对象及数组类型具备约束力,注意区别)。这可能不是我们想要的。解决办法就是在 PHP 脚本文件的第一条语句的位置放上:declare(strict_types=1);。这是个文件级别的指令,同时不影响其他包含文件——主要是考虑向后兼容及不影响各类扩展、内建代码。

按要求加上 declare(strict_types=1); 指令之后,运行下图代码就会报错:

小结

可见 PHP 的类型提示是个非常棒的功能!在不失弱类型语言方便、灵活特点的前提下,提供了一种运行时保护措施,有助于团队协作,无疑在灵活性与规范化之间取得了巧妙平衡。这是一种浓浓的好味道,那些黑 PHP 的人,大概是不会懂的。让 PHP 走自己的路,春风十里,都不如 PHP!

顺带说说,PHP 的类型提示,可比截至当前 Python 3.6 中的类型提示强太多了,Python 3.6 中的类型提示充其量只是“好言规劝”或向IDE“友好反馈”类型应该是什么。

生成器委托(Generator Delegation)

生成器委托(Generator Delegation)是 PHP 7 添加的特性,官方文档描述是:

“In PHP 7, generator delegation allows you to yield values from another generator, Traversable object, or array by using the yield from keyword. The outer generator will then yield all values from the inner generator, object, or array until that is no longer valid, after which execution will continue in the outer generator.”。

生成器委托的形式为:yield <expr><expr>的结果得是可遍历对象或数组。

<?php
declare(strict_types=1);

$seh_seh_liām = function () {
    $generator = function () {
        yield from range(1, 3);

        foreach (range(4, 6) as $i) {
            yield $i;
        }
    };

    foreach ($generator() as $value) {
        echo "每天念 PHP 是最好的编程语言 6 遍...第 $value 遍...", PHP_EOL;
    }
};

$seh_seh_liām();

生成器返回表达式(Generator Return Expression)

生成器返回表达式(Generator Return Expression)为生成器函数提供了增强内力,在 PHP 7 之前是无法在生成器函数内返回值的。

举例如下:

<?php
$traverser = (function () {
  yield "foo";
  yield "bar";
  return "value";
})();

$traverser->getReturn();

foreach ($traverser as $value) {
    echo "{$value}", PHP_EOL;
}

$traverser->getReturn();  // "value"

生成器与Coroutine

来个直接点的例子。

<?php
declare(strict_types=1);

class Coroutine
{
    public static function create(callable $callback) : Generator
    {
        return (function () use ($callback) {
            try {
                yield $callback;
            } catch (Exception $e) {
                echo "OH.. an error, but don't care and continue...", PHP_EOL;
            }
       })();
    }

    public static function run(array $cos)
    {
        $cnt = count($cos);
        while ($cnt > 0) {
            $loc = random_int(0, $cnt-1);  // 用 random 模拟调度策略。
            $cos[$loc]->current()();
            array_splice($cos, $loc, 1);
            $cnt--;
        }
    }
}

$co = new Coroutine();

$cos = [];
for ($i = 1; $i <= 10; $i++) {
    $cos[] = $co::create(function () use ($i) { echo "Co.{$i}.", PHP_EOL; });
}
$co::run($cos);

$cos = [];
for ($i = 1; $i <= 20; $i++) {
    $cos[] = $co::create(function () use ($i) { echo "Co.{$i}.", PHP_EOL; });
}
$co::run($cos);

空合并操作符(Null Coalesce Operator)

直接上例子:

$name = $name ?? "NoName";  // 如果$name有值就取其值,否则设$name成"NoName"

飞船操作符(Spaceship Operator)

形式:(expr) <=> (expr)

左边运算对象小,则返回-1;左、右两边运算对象相等,则返回0;左边运算对象大,则返回1。

$name = ["Simen", "Suzy", "Cook", "Stella"];
usort($name, function ($left, $right) {
    return $left <=> $right;
});
print_r($name);

常量数组(Constant Array)

PHP 7 之前只允许类/接口中使用常量数组,现在 PHP 7 也支持非类/接口的普通常量数组了。

define("USER", [
  "name"  => "Simen",
  "sex"   => "Male",
  "age"   => "38",
  "skill" => ["PHP", "MySQL", "C"]
]);
// USER["skill"][2] = "C/C++";  // PHP Fatal error:  Cannot use temporary expression in write context in...

统一了变量语法

$goo = [
    "bar" => [
        "baz" => 100,
        "cug" => 900
    ]
];

$foo = "goo";

$$foo["bar"]["baz"];  // 实际为:($$foo)['bar']['baz']; PHP 5 中为:${$foo['bar']['baz']};
                      // PHP 7 中一个笼统的判定规则是,由左向右结合。

Throwable 接口

这是 PHP 7 引进的一个值得期待的新特性,将极大增强 PHP 错误处理能力。PHP 5 的 try ... catch ... finally 无法处理传统错误,如果需要,你通常会考虑用 set_error_handler() 来 Hack 一下。但是仍有很多错误类型是 set_error_handler() 捕捉不到的。PHP 7引入 Throwable 接口,错误及异常都实现了 Throwable,无法直接实现 Throwable,但可以扩展 \Exception 和 \Error 类。可以用 Throwable 捕捉异常跟错误。\Exception 是所有PHP及用户异常的基类;\Error 是所有内部PHP错误的基类。

$name = "Tony";
try {
    $name = $name->method();
} catch (\Error $e) {
    echo "出错消息 --- ", $e->getMessage(), PHP_EOL;
}

try {
    $name = $name->method();
} catch (\Throwable $e) {
    echo "出错消息 --- ", $e->getMessage(), PHP_EOL;
}

try {
    intdiv(5, 0);
} catch (\DivisionByZeroError $e) {
    echo "出错消息 --- ", $e->getMessage(), PHP_EOL;
}

use 组合声明

use 组合声明可以减少 use 的输入冗余。

use PHPGoodTaste\Utils\{
    Util,
    Form,
    Form\Validation,
    Form\Binding
};

一次捕捉多种类型的异常 / 错误

PHP 7.1 新添加了捕获多种异常/错误类型的语法——通过竖杠“|”来实现。

try {
      throw new LengthException("LengthException");
    //   throw new DivisionByZeroError("DivisionByZeroError");
    //   throw new Exception("Exception");
} catch (\DivisionByZeroError | \LengthException $e) {
    echo "出错消息 --- ", $e->getMessage(), PHP_EOL;
} catch (\Exception $e) {
    echo "出错消息 --- ", $e->getMessage(), PHP_EOL;
} finally {
    // ...
}

可见性修饰符的变化

PHP 7.1 之前的类常量是不允许添加可见性修饰符的,此时类常量可见性相当于 public。PHP 7.1 为类常量添加了可见性修饰符支持特性。总的来说,可见性修饰符使用范围如下所示:

  • 函数/方法:public、private、protected、abstract、final
  • 类:abstract、final
  • 属性/变量:public、private、protected
  • 类常量:public、private、protected
class YourClass 
{
    const THE_OLD_STYLE_CONST = "One";

    public const THE_PUBLIC_CONST = "Two";
    private const THE_PRIVATE_CONST = "Three";
    protected const THE_PROTECTED_CONST = "Four";
}

iterable 伪类型

PHP 7.1 引入了 iterable 伪类型。iterable 类型适用于数组、生成器以及实现了 Traversable 的对象,它是 PHP 中保留类名。

$fn = function (iterable $it) : iterable {
    $result = [];
    foreach ($it as $value) {
        $result[] = $value + 1000;
    }
    return $result;
};

$fn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

可空类型(Nullable Type)

PHP 7.1 引入了可空类型。看看新兴的 Kotlin 编程语言的一个噱头特性就是可空类型。PHP 越来越像“强类型语言了”。对于同一类型的强制要求,可以设置其是否可空。

$fn = function (?int $in) {
    return $in ?? "NULL";
};

$fn(null);
$fn(5);
$fn();  // TypeError: Too few arguments to function {closure}(), 0 passed in ...

Void 返回类型

PHP 7.1 引入了 Void 返回类型。

function first(): void {
    // ...
}

function second(): void {
    // ...
    return;
}

www.phpzy.comtrue/php/21978.htmlTechArticlePHP 7 新特性,php新特性 转载自: https://zhuanlan.zhihu.com/p/27694633 https://zhuanlan.zhihu.com/p/27847880 https://zhuanlan.zhihu.com/p/29478077 https://goghcrow.gitbooks.io/php7/content/xin-te-xing.html PHP 7 之前的类型提示...

相关文章

    暂无相关文章

PHP之友评论

今天推荐