最近把项目的PHP版本从7.0升级到了7.1,顺便系统学习了一下PHP 7.1的新特性,收获很大。PHP 7.1是PHP 7系列的一个重要版本,在PHP 7.0的基础上,增加了很多新特性,也做了很多优化,性能更好,语法更现代,开发体验也更好。
但是很多PHP开发者,可能还在用PHP 5.x,或者虽然升级到了7.x,但是对7.1的新特性不了解,还是在用老的写法,没有享受到新版本带来的便利。今天就来分享一下我学习PHP 7.1新特性的路线和经验,聊聊PHP 7.1到底有哪些重要的新特性,怎么系统地学习,怎么在项目中应用,以及我踩过的一些坑,希望能给想学习PHP 7.1的朋友一些参考,少走弯路,快速上手。
一、为什么要升级到PHP 7.1
在说新特性之前,先说说为什么要升级到PHP 7.1,升级有什么好处。
1. 性能提升
PHP 7.0相比PHP 5.6,性能就有了巨大的提升,几乎是翻倍的,而PHP 7.1在7.0的基础上,又做了很多优化,性能进一步提升,特别是在数组操作、字符串处理、函数调用等方面,都有优化。对于大流量的网站,升级到PHP 7.1,能显著提升性能,降低服务器负载,节省成本。
我们的项目升级到7.1之后,接口的平均响应时间降低了大概15%,服务器的CPU使用率也降低了一些,效果还是很明显的。
2. 新特性,开发效率更高
PHP 7.1增加了很多新特性,比如可空类型、void返回类型、类常量可见性、多异常捕获、list解构、负字符串偏移等,这些新特性能让代码更简洁,更健壮,更易读,开发效率更高,也能减少bug。
3. 更严格的类型检查,代码更健壮
PHP 7.0引入了标量类型声明和返回类型声明,PHP 7.1又增加了可空类型和void返回类型,类型系统越来越完善,能在开发阶段就发现很多类型错误,让代码更健壮,更易维护,也更适合大型项目和团队协作。
4. 官方支持,安全更新
PHP 5.6已经在2018年底停止官方支持了,PHP 7.0也在2018年底停止安全更新了,而PHP 7.1还在官方支持期内,会有安全更新和bug修复,用新版本更安全,更有保障。对于生产环境来说,用官方支持的版本是很重要的,不然出了安全漏洞,没有官方补丁,就很危险。
5. 生态完善,主流框架都支持
现在主流的PHP框架,比如Laravel、Symfony、ThinkPHP、Yii等,都已经支持PHP 7.1,甚至要求PHP 7.1以上,很多新的框架和扩展,也都是基于PHP 7+开发的,升级到7.1,能更好地使用这些新的框架和工具,跟上生态的发展。
所以,不管是从性能、开发效率、代码质量,还是从安全、生态的角度,升级到PHP 7.1都是很有必要的,如果你还在用PHP 5.x或者7.0,建议尽快升级。
二、PHP 7.1的重要新特性
接下来,说说PHP 7.1有哪些重要的新特性,这也是学习的重点,我按照重要程度和使用频率,整理了一下。
1. 可空类型(Nullable Types)
这是PHP 7.1最重要的新特性之一,在类型声明的时候,在类型前面加个问号,就表示这个参数或者返回值可以是null,也可以是指定的类型。
比如:
function test(?string $name) {
var_dump($name);
}
test('hello'); // string(5) "hello"
test(null); // NULL返回类型也可以是可空的:
function getAge(): ?int {
return null; // 或者返回一个int
}这个特性非常实用,以前如果一个参数可以是null,也可以是string,就不能用类型声明,或者用两个类型(PHP 8.0才支持联合类型),现在有了可空类型,就可以很方便地声明,让类型系统更完善,代码更健壮。
在项目中,很多参数都是可空的,比如查询条件,可选参数等,用可空类型,能让代码更清晰,也能在开发阶段发现类型错误。
2. void返回类型
PHP 7.1增加了void返回类型,用来表示函数没有返回值。
比如:
function log(string $message): void {
echo $message;
// 不需要return,或者return;
}void返回类型的函数,不能有返回值,哪怕return null也不行,只能return;或者不写return。这个特性很适合那些没有返回值的函数,比如日志、输出、设置属性等,让函数的意图更清晰,也能防止不小心返回了值。
以前PHP没有void返回类型,函数有没有返回值全靠注释和约定,现在有了void,就能在语法层面保证,代码更严谨。
3. 类常量可见性
PHP 7.1之前,类的常量都是public的,不能设置可见性,PHP 7.1开始,类常量也可以设置public、protected、private可见性了,和类的属性、方法一样。
比如:
class Test {
public const PUBLIC_CONST = 'public';
protected const PROTECTED_CONST = 'protected';
private const PRIVATE_CONST = 'private';
}这个特性很实用,以前类常量都是public的,外部都能访问,没有封装性,现在可以设置private或者protected,把内部用的常量隐藏起来,只暴露需要公开的,封装性更好,代码更安全。
在项目中,很多类常量都是内部用的,不需要对外暴露,用private或者protected,能更好地封装,避免外部依赖内部常量,减少耦合。
4. 多异常捕获(Multi-catch)
PHP 7.1之前,try-catch的时候,一个catch只能捕获一种异常,如果要捕获多种异常,并且处理方式一样,就要写多个catch,代码很冗余。PHP 7.1开始,一个catch可以用竖线分隔,捕获多种异常。
比如:
try {
// 一些代码
} catch (FirstException | SecondException $e) {
// 处理这两种异常
}这个特性很实用,很多时候,几种异常的处理方式是一样的,比如记录日志,返回错误信息,以前要写好几个catch,代码重复,现在一个catch就搞定了,代码更简洁,更易维护。
5. list()解构增强
PHP 7.1对list()做了很多增强,更灵活,更强大。
首先,list()现在可以指定键名,用来解构关联数组:
$data = ['id' => 1, 'name' => 'test'];
list('id' => $id, 'name' => $name) = $data;
echo $id; // 1
echo $name; // test其次,list()可以嵌套,用来解构多维数组:
$data = [['id' => 1, 'name' => 'test'], ['id' => 2, 'name' => 'test2']];
list(list('id' => $id1, 'name' => $name1), list('id' => $id2, 'name' => $name2)) = $data;还有,list()可以跳过某些元素,用空的位置就行:
list($a, , $c) = [1, 2, 3];
echo $a; // 1
echo $c; // 3另外,PHP 7.1还引入了list()的简写语法[],和数组的语法一样:
[$a, $b, $c] = [1, 2, 3];
['id' => $id, 'name' => $name] = ['id' => 1, 'name' => 'test'];这个简写语法非常好用,现在很多代码都用[]来解构数组,比list()简洁多了,特别是在遍历数据库查询结果的时候,很方便。
这些list()的增强,让数组解构变得非常灵活和强大,在处理数组数据的时候,能少写很多代码,更简洁,更易读。
6. 负字符串偏移
PHP 7.1开始,字符串的偏移量可以用负数了,表示从字符串末尾开始数,和数组的负偏移一样。
比如:
$str = 'hello';
echo $str[-1]; // o
echo $str[-2]; // l以前字符串的偏移量只能用正数,要取最后一个字符,得用strlen($str)-1,很麻烦,现在直接用-1就行,方便多了,也更直观。
这个特性虽然小,但是很实用,经常要取字符串末尾的字符,用负偏移就很方便。
7. 迭代器(iterable)伪类型
PHP 7.1增加了iterable伪类型,用来表示参数或者返回值可以是数组,也可以是实现了Traversable接口的对象(也就是迭代器,比如Generator、ArrayObject等)。
比如:
function traverse(iterable $items) {
foreach ($items as $item) {
// ...
}
}这个特性很适合那些可以接受数组或者迭代器的函数,比如遍历、处理数据的函数,以前要么不写类型,要么写两个重载(PHP不支持函数重载),现在用iterable,就能同时接受数组和迭代器,类型更清晰,也更灵活。
8. Closure::fromCallable()
PHP 7.1增加了Closure::fromCallable()静态方法,用来把一个可调用的结构(比如函数、方法)转换成一个Closure对象。
比如:
function test($a, $b) {
return $a + $b;
}
$closure = Closure::fromCallable('test');
echo $closure(1, 2); // 3这个特性在一些需要把函数当成闭包传递的场景很有用,比如回调函数、函数式编程等,比以前用匿名函数包装更方便,也更高效。
9. 异步信号处理(pcntlasyncsignals)
PHP 7.1增加了pcntlasyncsignals()函数,用来开启异步信号处理,以前处理信号需要用declare(ticks=1),性能很差,现在用pcntlasyncsignals(true),就能开启异步信号处理,性能更好,也更方便。
这个特性在需要处理信号的场景,比如守护进程、命令行脚本、多进程编程等,很有用,比以前的ticks方式高效多了。
10. 其他小特性和优化
除了上面这些比较重要的,PHP 7.1还有一些小特性和优化:
- 支持在闭包中使用$this,不用再use ($this)了,PHP 7.1开始,闭包默认绑定了$this。
- 增加了mbord()、mbchr()、mb_scrub()等多字节字符串函数。
- 增加了hash_hkdf()函数,实现HKDF密钥派生。
- 增加了opensslgetcurve_names()函数,获取支持的椭圆曲线名称。
- 优化了数组操作、字符串处理、内存使用等,性能进一步提升。
- 废弃了一些旧的特性,比如mcrypt扩展(移到PECL)、e修饰符等,让语言更干净。
这些小特性和优化,虽然不常用,但是在特定场景下还是很有用的,了解一下也好。
三、我的学习路线和方法
了解了有哪些新特性之后,说说我是怎么学习的,我的学习路线和方法,供大家参考。
第一步:先看官方文档,全面了解
我学习新特性,第一步都是先看官方文档,PHP的官方文档写得非常好,很详细,每个新特性都有说明,有例子,是最好的学习资料。
PHP 7.1的新特性,官方文档有专门的页面:从PHP 7.0.x 移植到 PHP 7.1.x,里面详细列出了所有的新特性、不兼容的变更、废弃的特性、新增的函数和类等,非常全面,我第一遍就是把这个页面从头到尾看了一遍,对7.1的新特性有了一个全面的了解,知道有哪些东西,大概是干什么的。
看官方文档的时候,不用一下子全部记住,先有个印象,知道有哪些特性,大概怎么用,后面用到的时候再回来细看就行。
第二步:重点特性,动手写代码练习
看完官方文档,有了全面了解之后,第二步就是针对那些重要的、常用的特性,动手写代码练习,加深理解,真正掌握。
我把上面列的那些重要新特性,一个一个地写了小例子,动手试了试,比如可空类型,我就写了几个函数,试了试传null和传正常类型的情况,看看报错是什么样的;比如多异常捕获,我就写了个try-catch,抛出不同的异常,看看是不是都能捕获到;比如list解构,我就写了各种数组,试了试指定键名、嵌套、跳过元素、简写语法等。
动手写代码是最重要的,光看文档是记不住的,只有自己动手写一写,试一试,才能真正理解,才能记住,也才能发现一些文档里没说的细节和坑。
第三步:在实际项目中应用,逐步替换
学完了,练习完了,第三步就是在实际项目中应用,把老的写法逐步替换成新特性的写法,在实践中巩固,真正把新特性用起来。
我是先在新写的代码里用新特性,比如新写的函数,都加上类型声明,可空的就用可空类型,没有返回值的就用void,类常量设置合适的可见性,异常捕获用多异常捕获,数组解构用[]简写等。
然后,在重构老代码的时候,逐步把老的写法替换成新特性的写法,比如老的list()替换成[]简写,老的多个catch合并成多异常捕获,给老的函数加上类型声明和返回类型,给类常量加上可见性等。
在项目中应用,是学习的最好方式,因为实际项目中的场景更复杂,能遇到各种各样的情况,也能真正体会到新特性带来的好处,以及需要注意的地方。
第四步:注意不兼容变更,避免踩坑
学习新特性的同时,也要注意PHP 7.1的不兼容变更,也就是那些和老版本不一样的地方,升级的时候可能会导致老代码出问题,要特别注意,避免踩坑。
PHP 7.1比较重要的不兼容变更有:
- 当传递参数过少时,会发出警告,以前只是Notice,现在是Warning。
- 移除了e修饰符(pregreplace的e修饰符),要用pregreplace_callback代替。
- 废弃了mcrypt扩展,移到PECL,如果项目用了mcrypt,要换成openssl或者其他加密库。
- 字符串的非法偏移量(比如非整数的键),会抛出警告,并且结果是null。
- list()不能再用来拆分字符串了,以前可以,现在不行了,要用str_split。
- 一些函数的参数和返回值有变化,比如count()现在对不可数的对象会抛出警告。
这些不兼容变更,在升级之前一定要检查一下,看看项目里有没有用到这些特性,如果有,要先修改,再升级,不然升级之后可能会出问题。我升级的时候,就遇到了老代码用了pregreplace的e修饰符,升级之后报错了,后来改成pregreplace_callback就好了。
第五步:持续学习,关注最佳实践
最后,学习不是一蹴而就的,要持续学习,关注社区的最佳实践,看看别人是怎么用这些新特性的,有什么好的经验和坑,不断改进自己的代码。
我平时会关注PHP的官方博客、PHP社区、技术博客、GitHub上的开源项目,看看别人的代码是怎么写的,有什么好的实践,比如Laravel、Symfony这些主流框架,都是怎么用PHP新特性的,学习他们的写法,应用到自己的项目中。
另外,也要关注PHP的新版本,比如PHP 7.2、7.3、7.4、8.0,每个版本都有新特性,持续学习,跟上语言的发展,不要停留在老版本的写法上。
四、踩过的坑和注意事项
在学习和升级的过程中,我也踩了一些坑,分享给大家,避免踩同样的坑。
1. 可空类型和默认值的关系
用可空类型的时候,要注意和默认值的关系,如果一个参数有默认值null,那么它的类型自动就是可空的,不需要再加问号,当然加了也没错,但是要注意一致性。
比如:
function test(?string $name = null) {
// 可以
}
function test(string $name = null) {
// 也可以,PHP会自动把有默认null的参数当成可空的
}这两种写法都可以,但是建议统一,要么都加问号,要么都不加,保持代码风格一致。我一般是如果参数可空,不管有没有默认值,都加上问号,这样更清晰,一眼就能看出是可空的。
2. void返回类型不能返回值
用void返回类型的时候,要注意,函数里不能有返回值,哪怕return null也不行,只能return;或者不写return,不然会报错。
比如:
function test(): void {
return null; // 错误,void函数不能返回值
}
function test(): void {
return; // 正确
}
function test(): void {
// 不写return,正确
}这个是刚开始用的时候容易犯的错,要注意,void就是没有返回值,什么都不能返回。
3. 类常量可见性,继承的时候要注意
用类常量可见性的时候,要注意继承的规则,和方法、属性的可见性规则一样,子类不能把父类的public常量改成protected或者private,但是可以把protected的改成public,也就是可见性只能放宽,不能收紧。
还有,接口里的常量,只能是public的,不能设置protected或者private,因为接口的常量本来就是公开的。
这些规则和类的属性、方法是一样的,但是刚开始用的时候,可能会忽略,要注意一下。
4. list()解构,键名要对应
用list()指定键名解构关联数组的时候,要注意,键名必须和数组里的键名完全对应,不然会得到null,并且会发出警告。
比如:
$data = ['id' => 1, 'name' => 'test'];
list('id' => $id, 'age' => $age) = $data;
// $age是null,并且会有警告,因为$data里没有'age'这个键所以,解构的时候要确保键名是存在的,或者先判断一下,避免警告。
5. 负字符串偏移,老代码要注意
用负字符串偏移的时候,要注意,如果偏移量超出了字符串的长度,会返回空字符串,并且发出警告,和正偏移一样。
还有,老代码里如果有把字符串当数组用,并且用了负键名的,要注意,PHP 7.1之前,字符串的负偏移是不支持的,会被当成0,现在支持了,结果可能不一样,要检查一下老代码有没有这种情况。
6. 升级前要充分测试
最后,也是最重要的,升级PHP版本之前,一定要充分测试,把项目的所有功能都测一遍,特别是那些用到了不兼容变更的地方,确保没有问题,再上生产环境。
最好是先在测试环境升级,跑一遍单元测试、功能测试,看看有没有报错,有没有异常,没问题了,再灰度上线,先上一台机器,观察一段时间,没问题了再全量上线,不要一下子全量升级,不然出了问题影响很大。
我们升级的时候,就是先在测试环境测了一周,改了几个不兼容的地方,然后灰度上了一台机器,观察了两天,没问题了才全量上线的,整个过程很顺利,没有出大问题。
五、学习资源推荐
最后,给想学习PHP 7.1的朋友推荐一些学习资源:
1. 官方文档
首选肯定是官方文档,PHP的官方文档写得非常好,很详细,有中文,是最好的学习资料:
- PHP 7.1 新特性:https://www.php.net/manual/zh/migration71.new-features.php
- 从PHP 7.0移植到7.1:https://www.php.net/manual/zh/migration71.php
- PHP手册:https://www.php.net/manual/zh/
2. 官方RFC
如果想深入了解每个新特性的设计思路和讨论过程,可以看PHP的RFC,每个新特性都是先有RFC,讨论通过了才会加入PHP,RFC里有详细的设计、讨论、投票过程,能帮助你更深入地理解:
- PHP RFC:https://wiki.php.net/rfc
3. 技术博客和社区
- 廖雪峰的PHP教程:比较基础,适合入门。
- 菜鸟教程的PHP教程:也是基础教程,适合入门。
- SegmentFault、掘金、知乎的PHP板块:有很多PHP相关的技术文章和讨论。
- PHP官方博客:https://www.php.net/,会发布PHP的版本更新和新闻。
4. 开源项目
看优秀的开源项目的代码,是学习新特性最好的方式之一,看看别人是怎么用的:
- Laravel:最流行的PHP框架,代码质量很高,用了很多PHP新特性。
- Symfony:另一个优秀的PHP框架,代码很规范。
- Composer:PHP的包管理工具,代码也很优秀。
看这些项目的源码,学习他们的写法和最佳实践,应用到自己的项目中,进步会很快。
六、写在最后
PHP 7.1新特性学习路线:我是怎么入门的。
以上就是我学习PHP 7.1新特性的路线和经验,从为什么要升级,到PHP 7.1的重要新特性,到我的学习方法,到踩过的坑,到学习资源,做了一个比较全面的分享,希望能给想学习PHP 7.1的朋友一些参考。
PHP是一门一直在进步的语言,从PHP 5到PHP 7,再到现在的PHP 8,每一个版本都有很多新特性,性能越来越好,语法越来越现代,开发体验越来越好,作为PHP开发者,我们也要持续学习,跟上语言的发展,不要一直停留在老版本的写法上,要学会用新特性,写出更简洁、更健壮、更易维护的代码。
当然,学习新特性不是为了炫技,不是为了用而用,而是为了提升开发效率,提升代码质量,解决实际问题,所以在使用的时候,要根据实际场景,选择合适的特性,不要滥用,也不要为了用新特性而把代码搞得很复杂,简洁、清晰、易维护,才是最重要的。
我自己也还在学习中,PHP的新特性还有很多,PHP 8的联合类型、命名参数、匹配表达式、属性等,也都很值得学习,后面我也会继续学习,继续分享。
最后,用一句话结尾:"技术在不断发展,学习是一个持续的过程,保持好奇心,保持学习的热情,才能不被时代淘汰。"愿我们都能持续学习,不断进步,写出更好的代码,做出更好的产品。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录