个性化阅读
专注于IT技术分析

PHP 7简介:新增功能和已消失的功能

本文概述

在PHP世界中, 2015年最激动人心的事件之一就是PHP 7的发布, 距上一个主要版本PHP 5的发布已经过去了10年。向前迈出了一大步, PHP 7引入了许多新功能和性能升级。

但是, 它也删除了旧的, 过时的功能, 从而引入了一些兼容性中断, 使较旧的应用程序更难迁移到新版本。如果打算在PHP 7之上计划迁移现有应用程序或构建新应用程序, 本指南将作为一个快速指南。

但是, 等等, PHP 6去哪了?

如果你最近没有使用过PHP, 你可能想知道PHP 6发生了什么, 为什么从PHP 5跳到PHP 7?好吧, 长话短说, PHP 6失败了。版本6的主要功能是对Unicode字符的本地支持, 因为PHP主要用于Web开发, 并且Web需要Unicode, 因此将Unicode带入PHP的举动是有意义的。

这个想法是将对Unicode的完全支持带到核心本身。它将为语言带来扩展的功能, 从使用愚蠢的表情符号作为变量和函数名称的功能到强大的国际字符串功能。例如, 当另一种语言使用的大写和小写字母不同于英语时, 或者需要将汉字名称转换为英语时。

PHP 6雄心勃勃,但很垃圾。这就是我们最终得到PHP 7的过程,在此过程中跳过了版本6。

PHP 6雄心勃勃, 但很垃圾。这就是我们最终得到PHP 7的过程, 在此过程中跳过了版本6。

鸣叫

不幸的是, 这个雄心勃勃的计划被证明是比预期更大的问题。必须将许多代码库移植为支持Unicode和重要扩展的Unicode, 这被证明是乏味而棘手的。这减慢了该语言其他功能的开发, 使许多PHP开发人员在此过程中感到沮丧。出现了其他障碍, 这导致对开发本机Unicode支持的兴趣减少, 最终导致该项目被放弃。

由于已经为PHP 6及其Unicode支持编写了书籍和文章等资源, 因此将新版本重命名为PHP 7以避免混淆。

无论如何, 在悲惨的过去中有足够的时间, 让我们看看PHP 7带给聚会的什么。

性能战, PHP 7与PHP 5

几乎所有更新都将带来较小的性能升级。但是, 这次PHP与以前的版本相比有了重大改进, 使纯粹的性能成为PHP 7最吸引人的功能之一。这是” PHPNG”项目的一部分, 该项目解决了Zend Engine本身的内部问题。

通过重构内部数据结构并以抽象语法树(AST)的形式在代码编译中添加一个中间步骤, 其结果是优越的性能和更有效的内存分配。数字本身看起来很有希望;实际应用程序上进行的基准测试表明, PHP 7的平均速度是PHP 5.6的两倍, 并且在请求期间将内存消耗减少了50%, 这使PHP 7成为了Facebook HHVM JIT编译器的强大竞争对手。看一下Zend的这张信息图, 它描述了一些常见CMS和框架的性能。

PHP 7看上去和感觉都很熟悉,但已针对性能进行了调整。完善的Zend Engine和由此带来的性能提升带来了巨大的变化。

PHP 7看上去和感觉都很熟悉, 但已针对性能进行了调整。完善的Zend Engine和由此带来的性能提升带来了巨大的变化。

鸣叫

内存消耗的减少还使较小的计算机可以更好地处理请求, 并有机会围绕PHP构建微服务。内部更改, 特别是AST实施, 也为将来的优化打开了可能, 从而进一步提高了性能。正在考虑将JIT编译器的新内部实现用于将来的版本。

PHP 7语法糖

PHP 7带有新的语法功能。尽管没有扩展语言本身的功能, 但它们提供了一种更好或更简单的方法, 使你的代码更易于编写并令人赏心悦目。

团体进口报关单

现在, 我们可以将来自同一名称空间的类的导入声明分组到单个使用行中。这应该有助于以有意义的方式对齐声明, 或者仅在文件中保存一些字节。

use Framework\Module\Foo;
use Framework\Module\Bar;
use Framework\Module\Baz;

使用PHP 7, 我们可以使用:

use Framework\Module\{Foo, Bar, Baz};

或者, 如果你喜欢多行样式:

use Framework\Module{
    Foo, Bar, Baz
};

空合并运算符

这解决了PHP编程中的一个常见问题, 即我们想为另一个变量(如果实际上已设置)中的一个变量赋值, 或者为另一个变量提供不同的值。当我们处理用户提供的输入时, 通常会使用它。

PHP 7之前的版本:

if (isset($foo)) {
    $bar = $foo;
} else {
    $bar = 'default'; // we would give $bar the value 'default' if $foo is NULL
}

在PHP 7之后:

$bar = $foo ?? 'default';

这也可以与许多变量链接在一起:

$bar = $foo ?? $baz ?? 'default';

飞船操作员

宇宙飞船运算符<=>允许在两个值之间进行三向比较, 不仅可以通过返回1, 0或-1来指示两个值是否相等, 还可以指示哪个值更大。

在这里, 我们可以根据值的不同采取不同的操作:

switch ($bar <=> $foo) {
    case 0:
        echo '$bar and $foo are equal';
    case -1:
        echo '$foo is bigger';
    case 1:
        echo '$bar is bigger';
}

比较的值可以是整数, 浮点数, 字符串或什至数组。查看文档以了解如何将不同的值相互比较。 [https://wiki.php.net/rfc/combined-comparison-operator]

PHP 7中的新功能

但是, 当然, PHP 7还带来了令人兴奋的新功能。

标量参数类型和返回类型提示

PHP 7通过添加四个标量类型, 扩展了方法(类, 接口和数组)中以前的参数类型声明。整数(int), 浮点数(float), 布尔值(bool)和字符串(string)是可能的参数类型。

此外, 我们可以选择指定返回什么类型的方法和函数。支持的类型为bool, int, float, string, array, callable, Class或Interface的名称, self和Parent(用于类方法)

class Calculator
{
    // We declare that the parameters provided are of type integer
    public function addTwoInts(int $x, int $y): int {
        return $x + $y; // We also explicitly say that this method will return an integer
    }
}

类型声明允许构建更健壮的应用程序, 并避免从函数传递和返回错误的值。其他好处包括静态代码分析器和IDE, 如果缺少DocBlock, 它们可以更好地了解代码库。

由于PHP是弱类型语言, 因此将根据上下文强制转换参数和返回类型的某些值。如果我们在声明的参数类型为int的函数中传递值” 3″, 则解释器将其接受为整数, 并且不会引发任何错误。如果你不希望这样做, 可以通过添加声明指令来启用严格模式。

声明(strict_types = 1);

这是基于每个文件设置的, 因为全局选项会将代码存储库划分为基于全局严格性构建的存储库和不基于全局严格性构建的存储库, 当我们将两者的代码合并时会导致意外行为。

引擎异常

通过添加引擎异常, 可以轻松捕获和处理可能导致脚本终止的致命错误。

诸如调用不存在的方法之类的错误不会终止脚本, 而是引发可以由try catch块处理的异常, 从而改善了应用程序的错误处理。这对于某些类型的应用程序, 服务器和守护程序很重要, 因为致命错误否则会要求它们重新启动。随着致命错误使整个测试套件失效, PHPUnit中的测试也应该变得更加有用。将根据每个测试用例处理异常, 而不是错误。

向PHP 7添加引擎异常有助于防止脚本终止并改善错误处理。

PHP 7看上去和感觉都很熟悉, 但已针对性能进行了调整。完善的Zend Engine和由此带来的性能提升带来了巨大的变化。

鸣叫

PHP 7根据可能遇到的错误类型添加了许多新的异常类。为了保持版本之间的兼容性, 添加了新的Throwable接口, 该接口可以从引擎异常和用户异常中实施。为了避免引擎异常扩展基本异常类, 从而导致较早的代码捕获异常, 以前是不存在的, 因此这是必需的。

在PHP 7之前, 这会以致命错误终止脚本:

try {
    thisFunctionDoesNotEvenExist();
} catch (\EngineException $e) {
    // Clean things up and log error
    echo $e->getMessage();
}

匿名类

匿名类是匿名函数的表亲, 你可以在简单的短期实例中使用它们。匿名类很容易创建和使用, 就像常规对象一样。这是文档中的示例。

PHP 7之前的版本

class MyLogger {
  public function log($msg) {
    print_r($msg . "\n");
  }
}

$pusher->setLogger( new MyLogger() );

使用匿名类:

$pusher->setLogger(new class {
  public function log($msg) {
    print_r($msg . "\n");
  }
});

匿名类在单元测试中很有用, 特别是在模拟测试对象和服务时。通过创建提供我们要模拟的接口的简单对象, 这有助于我们避免繁重的模拟库和框架。

CSPRNG功能

添加了两个用于生成密码安全的字符串和整数的新函数。

random_bytes(int $len);

返回长度为$ len的随机字符串。

random_int(int $min, int $max);

返回介于$ min和$ max之间的数字。

Unicode代码点转义语法

与许多其他语言不同, 在PHP 7之前的PHP中, 没有一种方法可以对字符串文字Unicode编码点进行转义。此功能添加了转义\ u序列, 以使用其UTF-8代码点生成此类字符。这比直接插入字符更好, 这样可以更好地处理不可见字符以及具有相同图形表示但含义不同的字符。

回显” \ u {1F602}”; //输出????,

请注意, 这会更改\ u序列, 从而破坏现有代码, 因为它会更改行为。

发电机升级

PHP中的生成器还具有一些不错的附加功能。现在, 生成器具有一个return语句, 可用于使其在迭代后输出最终值。这可以用来检查生成器是否已正确执行, 并允许调用生成器的代码适当地处理各种情况。

此外, 生成器可以从其他生成器返回并产生表达式。这使他们可以将复杂的操作划分为更简单和模块化的单元。

function genA() {
    yield 2;
    yield 3;
    yield 4;
}

function genB() {
    yield 1;
    yield from genA(); // 'genA' gets called here and iterated over
    yield 5;
    return 'success'; // This is a final result we can check later
}

foreach (genB() as $val) {
    echo "\n $val"; // This will output values 1 to 5 in order
}

$genB()->getReturn(); // This should return 'success' when there are no errors.

期望

期望是对assert()函数的增强, 同时保持了向后兼容性。它们允许在生产代码中使用零成本断言, 并提供在断言失败时引发自定义异常的功能, 这在开发过程中可能很有用。

assert()成为PHP 7中的一种语言构造。断言仅应在开发和测试环境中用于调试目的。为了配置其行为, 我们提供了两个新的指令。

  • 断言断言
    • 1:生成并执行代码(开发模式)(默认值)
    • 0:生成代码, 但在运行时跳转
    • -1:不生成使成本为零的代码(生产模式)
  • 断言异常
    • 1:断言失败时抛出, 或者抛出未提供的异常, 或者抛出新的AssertionError对象(如果未提供异常)
    • 0:如上所述使用或生成Throwable, 但仅基于该对象生成警告, 而不是将其抛出(与PHP 5行为兼容)

准备从PHP 5迁移到PHP 7

主要版本的引入为你提供了一个机会, 可以更改/更新较旧的功能, 或者如果认为它们过旧或已过时了则将其删除。此类更改可能会导致较旧应用程序的兼容性遭到破坏。

这种版本升级带来的另一个问题是, 你依赖的重要库和框架可能尚未更新以支持最新版本。 PHP团队已尝试使新更改尽可能地向后兼容, 并允许尽可能轻松地迁移到新版本。较新的和更新的应用程序应该发现更容易转移到新版本, 而较旧的应用程序可能不得不决定收益是否超过成本, 可能选择不更新。

大多数休息时间较小, 可以轻松缓解, 而其他休息时间可能需要更多的精力和时间。基本上, 如果在安装PHP 7之前在应用程序中有过时警告, 则可能会收到错误, 这些错误会破坏应用程序, 直到修复。你被警告了吧?

旧的SAPI和扩展

最重要的是, 像mysql扩展一样删除了旧的和不建议使用的SAPI(但是你一开始不应该使用它, 对吧?)。有关扩展名和已删除功能的完整列表, 可以在此处和此处查看此RFC。

此外, 其他SAPI也已移植到PHP 7。

PHP 7删除了旧的SAPI和扩展的负载。我们猜测它们不会被遗漏。

PHP 7删除了旧的SAPI和扩展的负载。我们猜测它们不会被遗漏。

鸣叫

统一变量语法

此更新进行了一些更改, 以支持变量-变量构造的一致性。如下所示, 这允许使用带有变量的更高级的表达式, 但是在某些其他情况下会引入行为更改。

                        // old meaning            // new meaning
$$foo['bar']['baz']     ${$foo['bar']['baz']}     ($$foo)['bar']['baz']
$foo->$bar['baz']       $foo->{$bar['baz']}       ($foo->$bar)['baz']
$foo->$bar['baz']()     $foo->{$bar['baz']}()     ($foo->$bar)['baz']()
Foo::$bar['baz']()      Foo::{$bar['baz']}()      (Foo::$bar)['baz']()

这将破坏应用程序访问此类值的行为。另一方面, 你可以执行以下一些整洁的操作:

// Nested ()
foo()(); // Calls the return of foo()
$foo->bar()();

// IIFE syntax like JavaScript
(function() {
    // Function body
})();

// Nested ::
$foo::$bar::$baz

旧样式标签已删除

开头/结尾标签<%…%>, <%= …%>, <script language =” php”> … </ script>不再有效。用有效的替换它们应该很容易, 但是, Weirdo, 你到底在使用它们吗?

类, 接口和特征的名称无效

由于添加了诸如参数和返回类型类, 接口和特征之类的结果, 因此不再具有以下名称:

  • 布尔
  • int
  • float
  • String
  • null
  • true
  • false

这些会导致使用它们的现有应用程序和库中断, 但它们应该易于修复。另外, 尽管它们不会引起任何错误且有效, 但不应保留以下内容, 以备将来使用:

  • 资源
  • Object
  • 混合的
  • 数字

避免使用它们应该使你免于将来进行更改的工作。

有关可能破坏兼容性的完整更改列表, 请查看此文档。

你还可以使用php7cc, 它检查你的代码并可以检测到如果使用PHP 7可能出现的任何潜在问题。但是, 当然, 没有比安装PHP 7自己看的更好的方法了。

潜在的PHP 7兼容性问题

PHP 7基础结构兼容性

许多托管服务已开始增加对PHP 7的支持。这对共享托管提供商来说是个好消息, 因为性能的提高将使他们能够增加其硬件上的客户端网站的数量, 从而减少其运营费用并提高利润。对于客户本身, 在这种情况下, 他们不应该期望获得太大的提升, 但是公平地讲, 共享主机无论如何都不是一种以性能为导向的选择。

另一方面, 提供虚拟专用服务器或专用服务器的服务将获得这种性能提升的全部好处。一些PaaS服务(如Heroku)早就支持PHP 7, 但其他服务(如AWS Beanstalk和Oracle的OpenShift)则落后。请检查你的PaaS提供商的网站, 以了解是否已经支持PHP 7, 或者在不久的将来还会提供支持。

当然, IaaS提供程序允许你控制硬件并安装PHP 7(如果需要, 可以进行编译)。 PHP 7软件包已可用于主要的IaaS环境。

PHP 7软件兼容性

除了基础结构兼容性之外, 你还需要注意潜在的软件兼容性问题。流行的内容管理系统, 如WordPress, Joomla和Drupal, 在其最新版本中增加了对PHP 7的支持。 Symfony和Laravel等主要框架也得到了全面的支持。

但是, 该提防了。此支持不会以附件, 插件, 程序包或CMS或框架称为它们的形式扩展到第三方代码。他们可能会遇到兼容性问题, 因此你有责任确保为PHP 7准备就绪。

对于活动的, 已维护的存储库, 这应该不是问题。但是, 缺少PHP 7支持的较旧且未维护的存储库可能会使整个应用程序无法使用。

PHP的未来

PHP 7的发行版删除了旧的和过时的代码, 并为将来的新功能和性能升级铺平了道路。另外, PHP有望很快获得更多的性能优化。尽管与以前的发行版有一些兼容性中断, 但是大多数问题还是很容易解决。

库和框架现在正在将其代码迁移到PHP 7, 从而提供了最新版本。我鼓励你尝试一下, 自己看看结果。也许你的应用程序已经兼容并且正在等待使用, 并从PHP 7中受益。

相关:PHP开发人员最常见的10个错误清单

赞(0)
未经允许不得转载:srcmini » PHP 7简介:新增功能和已消失的功能

评论 抢沙发

评论前必须登录!