作为PHP5的最后一个版本,也是目前使用最广泛的PHP版本,PHP 5.6始于公元2014年(不是1804年,嘿嘿),其第一个测试版PHP 5.6 alpha 1版于2014年1月发布。随机产生了第一个由国人(鸟哥,惠新宸)参与主研的性能大规模提升版本PHPNG(PHP next generation,下一代PHP),2015年基于PHPNG接着就产生PHP 7版本。PHP7带来了革命性的性能提高,其运行速率是5.6的两倍还高以及其他改善,比如64位支持、类型申明、运行时优化等。从2015年开始官方就一直推荐大家尽快升级到php7,虽然当时扩展支持还是很成问题。

根据最新的W3techs统计,目前PHP 7大概占了超过16.6%的PHP份额。 总体上PHP仍然拥有大约83%的网站服务器端开发语言的绝大多数比例。

根据PHP开发支持周期,到今年12月31日后,PHP 5.6不在有官方支持。所以现在只剩下半年时间你升级你的PHP到PHP7。此后PHP5的命运就会终结,而且就虫虫所致目前基本上绝大多数的框架和程序都已经完美的支持PHP7了。

性能测试:PHP 7.3比PHP 7.0快25%

有很多性能测试对比都揭示了PHP 7比PHP 5.6快至少2倍。下面是各大php框架心性能对比图:

下面最新Phoronix基准测试结果则显示了自PHP7发布以来PHP 7的性能对比情况。最新版本的PHP 7.3 Alpha比以初始版本的PHP 7在系能上的改善的也是相当客观的。根据最新数据PHP 7.3是比PHP 5.6快3倍!比PHP 7.0快25%。不说别的光这性能对比图就能给烈日炎炎的夏日带来丝丝凉意。而且这还可以直接体现在费用上,比如升级PHP7后,Badoo大概每年可减少100w美刀。

Badoo公司的数据:

PHP 7兼容行检查

截止目前基本上绝大多数的PHP都可以完美的支持PHP7.0了。但是可能你恰好有一些历史遗留的脚本和程序,那么也好办,社区已经有好多的工具做兼容性检查,甚至给出直接的代码转译,以下是几个值得推荐的工具:

php7cc:一个很不错的工具,不过目前已经不再更新了。(github地址: /sstalle/php7cc)

php7mar:PHP 7迁移助手,虫虫强烈推荐的工具。 (github地址:/Alexia/php7mar)

使用方法:

php mar.php -f="/path/to/project/root/" -r="/path/to/output/"

phan:PHP脚本的静态分析器。 可以做当做php 7的语法检查器。(github地址:/phan/phan)

使用方法:phan --project-root-directory --progress-bar -o phan.out

phpstan - PHP静态分析和兼容性检查工具。(github地址:/phpstan/phpstan)

PHP 7性能设置要点

1. Opcache

首先,确保已经启用了OpCache。可以通过主配置文件php.ini或它独特的配置文件opcache.ini文件(例如/etc/php/7.2/fpm/conf.d/10-opcache.ini)。来进行设置。

zend_extension=opcache.so

opcache.enable=1

opcache.enable_cli=1

可以使用phpinfo()检查,也可以通过终端命令

php -v or php -i | grep opcache.enable

确认PHP OpCache已启用后,很多的ln(a)mp套件都有一个opCache监控脚本,可以对其系能进行实时监控,如下图

2、设置合适的realpath_cache_size

通过设置合宜的realpath_cache_size值可以改善你服务器的并发:

realpath_cache_size = 256k

realpath_cache_ttl = 300

3、禁止mysqlnd.collect_statistics

mysqlnd.collect_statistics = Off

mysqlnd.collect_memory_statistics = Off

线上服务器选择禁止这两个选项,可以减少不必要的数据库访问。如果需要相关统计,可以使用MySQL工具或者监控。

4、使用新的编译器

GCC 4.8编译器下编译时PHP才能开启Global Register for opline and execute_data支持, 这个会带来5%左右的性能提升。

5、开启Transparent HugePage (透传大页)

内存默认是以4KB分页的,而虚拟地址和内存地址需要转换,转化时候需要进行搜索,为了加速转换过程,可以通过内存TLB(Translation Lookaside Buffer)来。所以通过启用大内存页可以增加TLB 缓存命中,从而提高性能。

设置系统支持:

sysctl vm.nr_hugepages=512

php.ini 增加支持

opcache.huge_code_pages=1

关于这个值,很多实践后发现启用透传大页面后会带来系统负载过高,cpu占用过高问题,这时候通过关闭就可以解决。所以这个参数需要实际情况斟酌测试使用。

6、开启PGO

PHP是专门为一个项目服务,比如一个 Wordpress或者drupal站点,就可以使用PGO提高性能。

PHP 7.3正在敲响我们的大门,它带来了新的实用功能,并弃用大量的错误和修复旧有BUG,目前的Beta 2版本于8月16日发布。

您可以下载当前的PHP 7.3版本以进行开发和测试,但请记住,目前这不应该在生产环境中使用。

在这篇文章中,我们将概述我认为最相关的功能和变化。但是,您可以随时查看PHP 7.3升级说明和PHP 7.3请求注释中的功能,更改和错误修复的完整列表。

灵活的Heredoc和Nowdoc语法

这可能是PHP 7.3中最相关的改进之一,我认为值得更多关注。因此,在深入研究PHP 7.3 heredoc / nowdoc之前,我们将快速概述这个有用的核心功能。

1.heredoc和nowdoc语法概述

heredoc语法提供了一种添加大量文本的方法,而无需像双引号那样转义。一个heredoc开始<<<后跟一个标记,并以相同的标记结束,然后是分号。这是一个例子:

print <<<EOT

Heredoc text behaves just like a double-quoted string, without the double quotes.

EOT;
 

nowdoc的行为很像heredoc,但有一些例外:

标识符用单引号括起来(<<<‘EOT’)

在nowdoc内部没有解析

这是nowdoc的一个例子:

print <<<'EOT'

Nowdocs are to single-quoted strings what heredocs are to double-quoted strings.

EOT;
 

Heredocs和nowdocs共享相同的规则来规范结束标记的使用:

结束标记必须从该行的第一列开始

标记必须遵循与PHP中任何其他标签相同的命名规则:它必须仅包含字母数字字符和下划线,并且必须以非数字字符或下划线开头。

PHP手册警告:

请注意,除了分号(;)之外,具有结束标识符的行必须不包含其他字符,这一点非常重要。这尤其意味着标识符可能不会缩进,并且在分号之前或之后可能没有任何空格或制表符。同样重要的是要意识到结束标识符之前的第一个字符必须是本地操作系统定义的换行符。这是\n在UNIX系统上,包括macOS。结束分隔符也必须后跟换行符。

PHP 7.2语法无效:

class foo {

    public $bar = <<<EOT

    bar

    EOT;

}

// Identifier must not be indented
 

PHP 7.2有效语法:

class foo {

    public $bar = <<<EOT

bar

EOT;

}
 

为了简短起见,在PHP 7.2中:

结束标记可能不会缩进

带有结束标记的行可能不包含空格或制表符等字符

结束标记之前的第一个字符必须是换行符

结束标记必须后跟换行符

很明显,heredoc和nowdoc语法是相当严格的,但PHP 7.3可能会通过以下改进稍微改变一下。

1.允许缩进关闭标记并剥离前导空格

使用PHP 7.3,我们可以缩进结束标记,我们可以安全地编写以下代码:

class foo {

    public $bar = <<<EOT

        bar

    EOT;

}
 

结束标记的缩进设置将从主体的每一行剥离的空白(或制表符)的数量。但要小心:关闭标记不应该比身体的任何其他线进一步缩进。

请参阅以下代码:

class foo {

    public $bar = <<<EOT

    bar

        EOT;

}
 

上面的代码会发出以下解析错误:

解析错误:行%d上的%s中的体缩进级别(期望至少缩进…)无效

剥离制表符和空格允许我们将heredoc / nowdoc的主体缩进到周围代码的相同级别,并且在主体的每一行之前没有不必要的空格。

我们可以使用制表符和空格来缩进,但我们不允许混合使用它们。这意味着我们必须对结束标记和正文的任何​​行使用相同的缩进字符。如果有不同的缩进字符,我们会期望一种不同类型的解析错误(无效缩进)。

2.从结算标记中删除尾随新行要求

目前,新行必须遵循标记才能终止heredoc / nowdoc。PHP 7.3会改变这一点,并允许我们在同一行终止heredoc / nowdoc。这是RFC的一个例子:

PHP 7.2有效语法:

$values = [<<<END

a

b

c

END

, 'd e f'];
 

PHP 7.3有效语法:

$values = [<<<END

a

b

c

END, 'd e f'];
 

无论如何,在选择标记的名称时要小心,因为“偶尔”如果它与你在heredoc / nowdoc主体中使用的单词相匹配,你可能会遇到错误。

在函数调用中允许使用尾随逗号

尾随逗号(或“最终逗号”)是附加到元素,参数或属性列表的逗号,它们在频繁附加新值的上下文中派上用场,因为它们可以防止由于缺少逗号而导致的错误。在PHP中,允许在数组中使用尾随逗号,从PHP 7.2开始,它们在分组命名空间中是允许的。

从PHP 7.3开始,函数声明中将允许使用尾随逗号。变量函数提供了一个上下文示例,其中尾随逗号非常有用:

foo(

    $bar,

    $baz,

);
 

我们在创建数组时可以使用尾随逗号compact(),以便返回格式化字符串sprintf(),或者合并数组时:

$newArray = array_merge(

    $arrayOne,

    $arrayTwo,

    ['foo', 'bar'],

);
 

此外,尾随逗号对调试很有用:

var_dump(

    $foo,

    $bar,

    $baz,

);

强大
 

unset()和isset():

unset(

    $foo,

    $bar,

    $baz,

);

isset(

    $foo,

    $bar,

    $baz,

);
 

方法调用和附件中也允许使用尾随逗号。

注意:此更改仅影响函数调用。函数声明语法不会改变。此外,不允许使用独立逗号,多个尾随逗号和引号。

JSON_THROW_ON_ERROR

PHP 7.3带来的最受欢迎的功能之一提供了一种处理JSON错误的新方法。这不是核心功能,而是JSON扩展的一个补充,它将改变json_decode()和json_encode()的错误行为。

目前,json_decode()返回null错误,但null也可以是有效的结果。这可能令人困惑,因为

只能通过调用json_last_error()或者知道是否发生错误json_last_error_msg(),它分别以机器可读和人类可读的形式返回全局错误状态。- PHP RFC

json_encode()返回FALSE错误。这更清楚,因为存在特定的错误值。无论如何,这两个函数既不会在出错时停止程序执行,也不会抛出任何警告。

PHP 7.3的提议:

该RFC而是提出了添加新的选项标志值json_decode()和json_encode(),JSON_THROW_ON_ERROR。传递此标志时,会更改这些函数的错误行为。全局错误状态保持不变,如果发生错误,否则将设置它,这些函数将抛出一个JsonException消息和代码设置为任何json_last_error()和json_last_error_msg()否则将分别。

下面是一个显示抛出JSON错误的简单方法的示例:

try {

    json_decode("{", false, 512, JSON_THROW_ON_ERROR);

}

catch (\JsonException $exception) {

    echo $exception->getMessage(); // echoes "Syntax error"

}
 

在出错时抛出异常将带来您在RFC上列出的几个优点。

注意:传递的无效深度参数json_decode()输出警告并返回NULL。此行为不会受到影响JSON_THROW_ON_ERROR。同样,参数解析错误不会受到影响JSON_THROW_ON_ERROR并继续产生警告。

list()参考分配

参考分配意味着什么?

请考虑以下行:

$b = &$a;
 

这里$b获取值$a,但该值不会从中复制$a到$b。在PHP中,我们可以通过引用分配值,这意味着两个变量可以指向相同的数据,并且对任何变量的每个更改都会影响原始数据。以下是PHP手册中的一个示例:

<?php

$a = 3;

$b = &$a; // $b is a reference to $a

print "$a\n"; // prints 3

print "$b\n"; // prints 3
 

现在,让我们改变以下的值$a:

$a = 4; // change $a

print "$a\n"; // prints 4

print "$b\n"; // prints 4 as well, since $b is a reference to $a, which has been changed
 

什么是list()构造以及如何使用PHP 7.3进行更改

列表()语言结构可以用来“就像它们是在一个数组指派变量”,但与list()我们目前不允许通过参考分配变量值。

PHP 7.3应该改变这一点,允许我们通过引用也使用list()构造来分配变量,如以下示例所示:

$array = [1, 2];

list($a, &$b) = $array;
 

这与:

$array = [1, 2];

$a = $array[0];

$b =& $array[1];
 

is_countable函数

PHP 7.3附带的另一个功能是is_countable()功能。我们在尝试count()不可数的东西时会收到错误。出于这个原因,为了避免警告,我们被迫添加以下代码:

if (is_array($foo) || $foo instanceof Countable) {

    // $foo is countable

}
 

这个RFC提出了函数is_countable(),true如果给定变量是一个数组,它返回,false否则它是一个可数变量。因此,上面的代码可以更改如下:

if (is_countable($foo)) {

    // $foo is countable

}
 

array_key_first(),array_key_last()

目前,我们可以使用reset(),end()和key()函数检索数组的第一个和最后一个键。不幸的是,使用这些函数,无法在不更改其内部状态的情况下收集数组的第一个或最后一个索引。其他选项通常会降低代码的可读性和性能。
此提议将通过向PHP核心添加两个新函数来更改此方案:

array_key_first()

array_key_last()

在PHP 7.3中,array_key_first()并array_key_last()允许取回第一和给定数组的最后一个关键,而不会影响内部数组指针。这些新功能允许我们编写不太

注意:最初的RFC提出了另外两个函数,array_value_first()并且array_value_last()这些函数在不同的投票中投票,但尚未获得批准,也不会成为PHP核心的参与者。

Argon2密码哈希增强功能

Argon2是在PHP 7.2中实现的散列算法,作为Bcrypt算法的替代算法。PHP 7.2引入了PASSWORD_ARGON2I常量,可用于password_*函数:

password_hash('password', PASSWORD_ARGON2I);
 

自第一次实现以来,添加了一个新的Argon2变体,因此,在撰写本文时,Argon2有三种变体:

Argon2d最大限度地抵御GPU破解攻击。它更快,并使用依赖于数据的内存访问。

Argon2i使用与数据无关的内存访问,这是密码散列的首选。它更慢,因为它通过内存更多的通过,以防止权衡攻击。

Argon2id是一个混合版本,它结合了第一次通过内存的Argon2i方法和后续通过的Argon2d方法。

建议在Internet上使用Argon2id,除非有充分理由特别喜欢其他变体。

新RFC建议在password_ *函数中使用新PASSWORD_ARGON2ID常量实现Argon2id :

password_hash('password', PASSWORD_ARGON2ID);
 

实现与Argon2i实现相同,并且将接受相同的成本因素:

甲存储器成本它定义了应散列期间被消耗KIB的数(默认值是1 << 10,或1024 KIB,或1 MIB)

甲时间成本定义散列算法的迭代次数(默认为2)

甲并行因子,它设置散列(默认为2)时,将用于并行线程的数目

请参阅以下代码:

$options = ['memory_cost' => 1<<11, 'time_cost' => 4, 'threads' => 2];

password_hash('password', PASSWORD_ARGON2ID, $options);
 

弃用

以下函数/功能将在PHP 7.3中弃用,并且不会晚于PHP 8.0删除。

弃用并删除image2wbmp()

所述image2wbmp()函数输出或保存WBMP给定图像的版本。此函数有三个参数:图像资源,文件名(保存文件的路径)和前景色。
从PHP 5.0开始,它与imagewbmp()完全相同,因此该RFC建议弃用并删除它。
从PHP 7.3开始,每次调用image2wbmp()都会发出弃用警告。删除后,每次调用都会引发致命错误。

弃用和删除不区分大小写的常量

PHP目前支持区分大小写和不区分大小写的常量。无论如何,支持不区分大小写的常量,但被认为是功能上的不一致,并且使用起来很复杂。
该提案从以下前提开始:

类常量始终区分大小写

声明的全局常量const始终区分大小写

define()默认情况下,定义的常量区分大小写

此外,PHP语言参考明确指出:

默认情况下,常量区分大小写。按照惯例,常量标识符总是大写的。

话虽这么说,这个RFC提出了以下变化:

使用define()第三个参数设置为true- PHP 7.3 弃用调用

使用与声明不同的大小写(不包括true,false和null)来弃用不区分大小写的常量- PHP 7.3

删除声明不区分大小写的常量的可能性 – PHP 8.0

转换true,false并null从特例,常数为保留关键字- PHP 8.0

PHP 7.3的附加弃用

以下是PHP 7.3中不推荐使用的功能的快速列表。它并非详尽无遗,它们只是我个人认为更具相关性的弃用提案。有关建议的弃用的完整列表,请参阅PHP 7.3的弃用。

未记录的mbstring函数别名:有许多未记录的mbstring函数别名,它们是使用mb_前缀的等效函数的重复。例如,mbereg是别名mb_ereg。
所有这些函数都将被标记为已弃用,并且在编译期间遇到它们时将抛出弃用通知。

带整数针的字符串搜索功能:这些功能通常在字符串针上运行。如果给出非字符串指针,则将其转换为整数并作为字符的序数值应用(请参阅PHP手册中的更多内容)。这是RFC的一个例子:

$str = "There are 10 apples";

var_dump(strpos($str, "10")); // int(10)

var_dump(strpos($str, 10));   // bool(false)
 

这被认为是混乱并导致不可预测的问题,因为类型可能随用户数据源而改变。因此,如果将非字符串针传递给以下函数之一,则RFC建议发出弃用警告:

strpos

strrpos

stripos

strripos

strstr

strchr

strrchr

stristr

在PHP 8.0中,应删除弃用警告,并且针应自动转换为字符串。

正在寻找改进WordPress开发工作流程的方法?

Kinsta的托管解决方案是由开发人员为开发人员构建的。Git,PHP 7,SSH和WP-CLI,以及强大的登台和克隆环境为您提供了更快地构建网站所需的工具!

查看我们的高级功能

fgetss()功能和string.strip_tags流过滤器:fgetss()与string.strip_tags从流条标签,因为它们读取它。函数和过滤器都暴露了strip_tags()功能,使得实现strip_tags()更加复杂,因为需要流式状态机。此外,RFC指出了这些功能的另一个缺点:

另一方面,这些功能似乎没什么用处。strip_tags()由于其局限性和已知错误,本身已经很少有合法的应用程序。除此之外,无需为流应用程序提供本机支持。

因此RFC建议标记fgetss(),gzgetss()并SplFileObject::fgetss()弃用。

概要

在撰写本文时,PHP 7.3处于Beta 2阶段,根据准备任务时间表,它将于12月中旬正式发布。它将带给我们如灵活的heredocs和nowdocs,函数调用中的尾随逗号,list()参考分配等等。

PHP7.3发布啦的更多相关文章

  1. PHP 源码加密扩展(php-beast)PHP7 版本发布

    此版本主要支持PHP7,在github(https://github.com/liexusong/php-beast)上选择php7分支然后编译安装即可.   来源于:https://github.c ...

  2. 随着php7的发布我个人觉得有必要进行一下历史回顾和整理

    先看下人尽皆知的发展历史: HP 继承自一个老的工程,名叫 PHP/FI.PHP/FI 在 1995 年由 Rasmus Lerdorf 创建,最初只是一套简单的 Perl 脚本,用来跟踪访问他主页的 ...

  3. PHP7革新与性能优化

    有幸参与2015年的PHP技术峰会(PHPCON),听了鸟哥(惠新宸)的关于PHP7的新特性和性能优化的分享,一切都令人感到激动.鸟哥是国内最权威的PHP专家,他的分享有很多非常有价值的东西,我通过整 ...

  4. PHP7最高性能优化建议

    PHP7已经发布了, 作为PHP10年来最大的版本升级, 最大的性能升级, PHP7在多放的测试中都表现出很明显的性能提升, 然而, 为了让它能发挥出最大的性能, 我还是有几件事想提醒下. PHP7 ...

  5. 让PHP7达到最高性能的几个Tips(转)

    PHP7已经发布了, 作为PHP10年来最大的版本升级, 最大的性能升级, PHP7在多放的测试中都表现出很明显的性能提升, 然而, 为了让它能发挥出最大的性能, 我还是有几件事想提醒下. PHP7 ...

  6. 让PHP7达到最高性能的几个Tips

    PHP7 已经发布了,作为PHP十年来最大的版本升级,最大的性能升级,PHP7在多放的测试中都表现出很明显的性能提升,然而,为了让它能发挥出最大的性能,我还是有几件事想提醒下. PHP7 VS PHP ...

  7. php7性能、兼容性和稳定性探讨

    前几天看到php7发布了beta1版本,想了解一下php7到底折腾了些啥东西出来.这一了解发现不得了了,改变还挺多的.最最重要的方面就是性能提升了不少,这边有一个pdf文件是惠新宸(鸟哥,php核心开 ...

  8. 深入理解PHP7之zval

    PHP7已经发布, 如承诺, 我也要开始这个系列的文章的编写, 今天我想先和大家聊聊zval的变化. 在讲zval变化的之前我们先来看看zval在PHP5下面是什么样子 PHP5zval回顾在PHP5 ...

  9. php7+新特性

    php7已经发布有段时间了,查了下正式版本的发布时间是2015年底,至于具体的新特性,在这里总结一下. 标量类型声明 php7新增了4种类型, 字符串(string), 整数 (int), 浮点数 ( ...

随机推荐

  1. Anaconda创建python(2.7/3.6)的虚拟环境后需要添加ipykernel

    今天在工作的过程中遇到这样一个问题:安装完Anaconda利用conda创建了虚拟环境,但是启动jupyter notebook之后却找不到虚拟环境中的python kernel.后来上网找到了解决办 ...

  2. Spring Boot 启动报错 Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 37

    使用命令 java -jar springBoot.jar  启动项目,结果报错如下: Exception at java.lang.String.substring(String.java:) at ...

  3. JAVA--未明确定义列

    原因:列明重复 可以加前缀或区别名以区分

  4. 【C++ STL】容器的选择

    c++提供了各具特长的容器,那么我们该如何选择最佳的容器? 缺省状态下应该选择vector,因为vector内部结构最简单,并允许随机存取,所以数据的存取十分方便,数据的处理也快. 如果经常要在头部和 ...

  5. 【转载】Java JVM : Xms Xmx PermSize MaxPermSize 区别

     转载自:http://cxh61207.iteye.com/blog/1160663 java JVM虚拟机选项: Xms Xmx PermSize MaxPermSize 区别 Xms 是指设定程 ...

  6. 注意for循环中变量的作用域

    for e in collections: pass 在for 循环里, 最后一个对象e一直存在在上下文中.就是在循环外面,接下来对e的引用仍然有效. 这里有个问题容易被忽略,如果在循环之前已经有一个 ...

  7. RSA host key has changed 错误

    RSA host key for mysharebook.cn has changed and you have requested strict checking.Host key verifica ...

  8. dp优化-四边形不等式(模板题:合并石子)

    学习博客:https://blog.csdn.net/noiau/article/details/72514812 看了好久,这里整理一下证明 方程形式:dp(i,j)=min(dp(i,k)+dp( ...

  9. [cerc2012][Gym100624A]20181013

    A 题意:n(n<=20)个国家,每个国家之间有一些债务关系,总体为负债的国家会破产,破产国家的债务关系全部消除.问哪些国家可能成为最后一个唯一存在的国家. 题解: 对于每一个状态,面对若干个负 ...

  10. js监听浏览器后退事件

    $(document).ready(function(e) {             var counter = 0;            if (window.history && ...