呼吁:是时候升级到PHP 8了!
Tillreetree 10月前

我知道你们打算用PHP 7.2一辈子,甚至都不想升级到PHP 7.4,因为觉得"能用就好"不太想升级嘛。

但是,你们要知道几个事实噢:

1. 在我写这个帖子的时候,最新版的PHP是8.2.10哦!
2. PHP 7.2于2020年11月30日停止支持。
3. PHP 7.4于2022年11月28日停止支持。
4. 而现在至少得有数万网站还在用PHP 7.2呢!

## 那为什么这些网站不升级PHP版本呢?

因为程序本身(有时还包括插件)不支持高于7.2的PHP,光是PHP 7.4就足够让部分插件无法正常工作了。

原装的Xiuno BBS 4.0.4最高支持PHP 7.2,因为程序核心用了些完全过时的东西(开发者对当时的开源环境感到非常失望,所以就不再更新了;让我联想到近期的“CEC-IDE事件”),比如get_magic_quotes_gpc()函数(可以直接用false替代),某些函数使用了花括号方式访问数组里的东西(需要手动修改)。

不过,好在有些喜欢Xiuno BBS的人修复了这些问题,比如第三方开发者制作的4.0.7版支持了PHP 8,并且还去掉了过时的代码。

至于插件嘛,因为插件开发者水平参差不齐,所以就出现了各种低质量、低效率的代码。

“低效率”的例子有很多,如“频繁读写数据库”、“循环嵌套”、“不用缓存系统”等。这两者还可以“强强联手”,这样性能就会变得很差哦。

例如:

```php
<?php
$tid_list = db_read('example_table',['list_id' => 10]); //读取帖子列表
$final_thread_list = array(); //输出帖子列表
foreach($tid_list as $this_tid) {
    $this_thread = thread_read($this_tid); //读取对应帖子
    $this_thread_tags = explode(',',$this_thread['tags']); //读取标签列表字符串,转换成数组
    $this_thread['tags_list'] = array(); //准备真正的标签列表
    foreach($this_thread_tags as $this_tag){ //我知道foreach超好用,但真的有必要嵌套循环吗?
        $this_thread['tags_list'][$this_tag] = tag_read($this_tag); //读取对应标签
    }
    $final_thread_list[] = $this_thread;
}
```

读/写一次数据库会消耗0.0001到0.001秒的时间,当$tid_list里有10项的时候还好,但当$tid_list里有100、1000、10000项的时候就会感受到明显的缓慢了。而论坛网站的特性就是“帖子越来越多”,所以像这样写终将会导致网站运行越来越慢。

不过,这个问题可以通过多使用缓存功能来解决哦。Xiuno BBS提供缓存功能的目的就是希望开发者多多利用,Xiuno BBS的特点之一就是“充分利用缓存功能,为用户提供顺畅的使用体验”。推荐在“读取”操作的时候优先使用缓存。

“低质量”的一个知名例子是“兔兔积分插件”的内容付费可以输入负数的bug。

我大致说一下这个bug:兔兔积分插件可以在发帖的时候设置付费内容,而“消耗积分”框用的是**文本框**而不是**数字框**,这就导致用户可以输入任意数量的积分,甚至可以输入负数!后端只做了是否为数字的校验,而负数是数字,所以能保存下来,结果用户在为内容付费的时候可以直接获得积分(相对应的,发帖人会扣除对应积分,能被扣到负数)。

当时插件开发者制作这个插件的时候,HTML5已经出现了,而HTML5给input元素带来了一系列新的type属性,用于规范输入框可以输入的内容,其中一种是number数字输入框,可以指定最小值、最大值,并且能保证用户只能输入数字,即使后端不做校验,也能获得符合要求的值。

更新到PHP 7.4~8.0后最常见的错误之一是“访问不存在的数组键”。

在过去的PHP版本中,当访问不存在的数组键时,PHP会显示警告并返回null值。这种行为可能会导致潜在的bug或错误在代码中被忽略,因为开发者可能会继续使用这个错误的值进行操作,而不知道存在问题。甚至有些开发者利用这个特性来判断"数组键是否存在",从而做出不同的处理。

让我们来看个例子吧:
```php
<?php
$demo_array = array(
    "en" => "Yes",
    "zh" => "",
    "es" => "",
    "fr" => "Oui",
);

if( is_null($demo_array["de"]) ) {
    // 不一定直接用if判断,有时还有二维数组foreach里用if判断
    // 而在二维数组foreach里用if判断有更高的风险,只要数组里缺少所需的键,可以导致整个程序崩溃,还增加debug难度
    $demo_array["de"] = "Ja";
}

var_dump($demo_array); //你猜会出现什么?
?>
```

在PHP7中,这段代码会正常输出一个有五个项的数组。但是在PHP8中,直接就会出错,而且不会输出数组内容。

PHP8强制开发者在访问数组键之前进行检查,以确保键是否存在。这样可以提前发现并解决潜在的问题,避免在后续代码中出现错误结果。

## 但是,人总得要走出自己的舒适圈嘛!

我在此呼吁开发者**升级自己的插件代码到PHP 8**。PHP 8采用了更严格的标准和语法,这可以帮助开发者减少潜在的bug和错误。遵循更严格的标准,就可以更好地规范自己的代码,提高插件的质量和可维护性。

PHP 8还引入了许多新的内置函数和特性,可以提升编程的效率和灵活性。比如**null合并运算符**(其实PHP 7就有了,但就是没人用,因为PHP 7放纵开发者可以不这么干),在处理可能为null的变量(如“需要访问数组中可能不存在的键值对”)时更加方便和安全,例如`$var = $_GET['thing'] ?? 'Default Value'`,如果 $_GET['thing'] 存在且不为null,那么 $var 就会被赋值为 $_GET['thing'] 的值;如果 $_GET['thing'] 不存在或为null,那么 $var 就会被赋值为 'Default Value'。

我在此也呼吁用户**是时候升级到PHP 8了**,当程序本体加上所使用的插件都支持PHP 8后,升级服务器运行的PHP到8就能让您的网站更快、更稳定,并提供更好的用户体验。

## 开发者们可以参考以下资料把自己的代码逐步升级到兼容PHP 8:
[从 PHP 7.2 移植到 PHP 7.3](https://www.php.net/manual/zh/migration74.php)
[从 PHP 7.3 移植到 PHP 7.4](https://www.php.net/manual/zh/migration80.php)
[从 PHP 7.4 移植到 PHP 8.0](https://www.php.net/manual/zh/migration81.php)
[从 PHP 8.1 移植到 PHP 8.2](https://www.php.net/manual/zh/migration82.php)
最新回复 (2)
全部楼主
  • adnim
    10月前 2
    0
    建议大佬把xiuno程序接力维护下去
  • Tillreetree 版主 楼主
    10月前 3
    0
    adnim 建议大佬把xiuno程序接力维护下去
    我不维护
返回