MoreRSS

site iconLuffy | 沈唁志修改

分享 PHP、Swoole 技术资源、实用插件、有趣网站和 WordPress 相关内容。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Luffy | 沈唁志的 RSS 预览

在命令行中输出带颜色的日志

2025-01-15 18:09:21

在命令行界面(CLI)中输出带颜色的日志不仅能提升可读性,还能帮助开发人员在调试时迅速区分不同类型的日志信息。

通过使用 ANSI 转义序列,我们可以很方便地控制输出文本的颜色、样式和其他显示效果,如加粗、下划线、反显等。

本文将详细介绍如何使用这些序列输出带颜色的日志。

什么是 ANSI 转义序列?

ANSI 转义序列是一种用于控制终端文本格式的字符序列。

它通常以 \033[\e[ 开头,后接不同的控制代码,最后以 m 结尾。

例如,\033[32m 表示设置文本颜色为绿色,\033[0m 用来重置样式。

利用 ANSI 转义序列,开发者可以灵活地在命令行中输出不同颜色和效果的文本。

常见的 ANSI 转义序列控制

  • \033[0m:关闭所有属性,恢复为默认设置
  • \033[1m:设置高亮度(加深显示)
  • \033[4m:设置下划线
  • \033[5m:设置闪烁
  • \033[7m:反显(替换背景色和前景色)
  • \033[8m:消隐(隐藏文本)
  • \033[30m\033[37m:设置前景色(字体颜色)
  • \033[40m\033[47m:设置背景色
  • \033[nA:光标上移 n 行
  • \033[nB:光标下移 n 行
  • \033[nC:光标右移 n 行
  • \033[nD:光标左移 n 行
  • \033[y;xH:设置光标位置为 y 行 x 列
  • \033[2J:清屏
  • \033[K:清除从光标到行尾的内容
  • \033[s:保存光标位置
  • \033[u:恢复光标位置
  • \033[?25l:隐藏光标
  • \033[?25h:显示光标

常见的颜色和效果

字体颜色(前景色)

  • 30: 黑色
  • 31: 红色
  • 32: 绿色
  • 33: 黄色
  • 34: 蓝色
  • 35: 紫色
  • 36: 深绿色
  • 37: 白色

背景颜色

  • 40: 黑色背景
  • 41: 红色背景
  • 42: 绿色背景
  • 43: 黄色背景
  • 44: 蓝色背景
  • 45: 紫色背景
  • 46: 深绿色背景
  • 47: 白色背景

显示效果

  • 0: 默认(无效果)
  • 1: 高亮(加深显示)
  • 2: 低亮(减弱显示)
  • 4: 下划线
  • 5: 闪烁
  • 7: 反显(替换前景色和背景色)
  • 8: 消隐(隐藏文本)

示例代码

  1. 简单的颜色输出

最简单的颜色控制是设置文本的前景色。例如,以下代码将输出绿色文本:

echo "\033[32m绿色\033[0m"

033[32m 设置文本为绿色,033[0m 用于重置所有属性,使后续输出恢复默认样式。

  1. 加粗和下划线

我们可以结合多种样式来增强文本的可读性。例如,下面的代码将输出一个带下划线的红色文本:

echo "\033[4;31m下划线红色\033[0m"

这里,4 表示下划线,31 表示红色。

  1. 发出声音提示

除了颜色和样式,ANSI 转义序列还可以控制终端的其他行为,比如发出声音。

这行命令会在终端发出一声铃声,同时输出一段普通文本:

echo "\007发出'咚~'一声\033[0m"

请注意,在某些终端环境下,铃声可能不会响起,尤其是在没有扬声器的设备上。

  1. 设置背景色和前景色

你还可以同时设置文本的前景色和背景色。例如,以下代码将输出一个白色背景和红色前景的文本:

echo "\033[47;31m白底红字\033[0m"

47 是背景色(白色),31 是前景色(红色)。

  1. 结合多个效果

通过组合多个效果,你可以创建更具视觉冲击力的输出。比如,以下代码将输出一个蓝色加粗下划线的文本:

echo "\033[1;4;34m蓝色加粗下划线\033[0m"

在这个示例中,1 表示加粗,4 表示下划线,34 表示蓝色。

  1. 光标控制和清屏

ANSI 转义序列还允许控制光标的位置和终端屏幕的清理。例如:

echo "\033[2J"  # 清屏
echo "\033[10;5H光标移动到第10行第5列\033[0m"
  1. 隐藏和显示光标

你还可以隐藏和显示光标:

echo "\033[?25l"  # 隐藏光标
echo "\033[?25h"  # 显示光标

实现效果

通过使用 ANSI 转义序列,我们可以轻松地为命令行中的输出添加颜色和样式。

这不仅能让调试日志变得更加易读,还能增强命令行工具的用户体验。

你可以根据需求结合不同的颜色、效果和光标控制,创建自定义的命令行输出,通过这些技术,命令行的输出变得更加生动和富有表现力,有助于开发人员快速识别关键信息。

PHP 中生成带毫秒的时间戳

2025-01-02 12:05:37

今天在对接一个 API 的时候,发现需要生成高精度的时间戳,格式为yyyyMMddHH24mmssSSS

本文将介绍两种常见的实现方式,并讨论它们的优缺点。

时间格式解析

格式 yyyyMMddHH24mmssSSS 的含义如下:

  • yyyy:四位数的年份(例如:2025)。
  • MM:两位数的月份(01-12)。
  • dd:两位数的日期(01-31)。
  • HH24:两位数的小时(24 小时制,00-23)。
  • mm:两位数的分钟(00-59)。
  • ss:两位数的秒(00-59)。
  • SSS:三位数的毫秒(000-999)。

例如,时间 2025-01-02 11:30:45.123 的格式化结果为:20250102113045123

使用 DateTime 类实现

以下是使用 DateTime 类生成毫秒时间戳的代码示例:

<?php
$dateTime = new DateTime();
// 获取当前时间的微秒数并计算为毫秒
$milliseconds = intval($dateTime->format('u') / 1000);
// 格式化时间
$formattedTime = $dateTime->format("YmdHi") . $dateTime->format("s") . sprintf("%03d", $milliseconds);
echo $formattedTime;

代码解析

  1. $dateTime->format('u') 返回当前时间的微秒(6 位数,例如 123456)。
  2. intval($dateTime->format('u') / 1000) 将微秒转换为毫秒(3 位数,例如 123)。
  3. 使用 sprintf("%03d", $milliseconds) 确保毫秒部分始终为 3 位数(不足时补零)。

示例输出

假设当前时间为 2025-01-02 11:30:45.123456,输出结果为:

20250102113045123

使用 microtime 函数实现

另一种方法是结合 microtime()date() 函数:

<?php
$microtime = microtime(true);
// 格式化时间到秒
$formattedDate = date('YmdHis', floor($microtime));
// 获取毫秒部分
$milliseconds = sprintf('%03d', ($microtime - floor($microtime)) * 1000);
// 拼接毫秒
$formattedDate .= $milliseconds;
echo $formattedDate;

代码解析

  1. microtime(true) 返回当前 Unix 时间戳,包含秒和小数部分。
  2. floor($microtime) 获取整数秒部分。
  3. ($microtime - floor($microtime)) * 1000 提取小数部分并转换为毫秒。
  4. 最终拼接秒部分和毫秒部分,生成完整的时间戳。

示例输出

假设当前时间为 2025-01-02 15:30:45.123456,输出结果为:

20250102153045123

对比分析

特性 使用 DateTime 使用 microtime()
代码简洁性 更加现代化,语义清晰 较为传统,需要手动处理毫秒
精度 取决于系统支持的时间精度 依赖 microtime() 的实现
扩展性 更容易与其他 DateTime 操作结合 适合处理与 Unix 时间戳相关的逻辑

统一验证输出

为了验证两种方法的输出是否一致,可以添加以下代码:

if ($formattedTime === $formattedDate) {
    echo "两种方法的输出一致:$formattedTime\n";
} else {
    echo "两种方法的输出不一致:\n第一种方法:$formattedTime\n第二种方法:$formattedDate\n";
}

总结

  • 如果你的项目主要使用 DateTime 类,建议采用第一种方法,代码语义更加清晰。
  • 如果需要与 microtime() 或 Unix 时间戳直接交互,可以选择第二种方法。

选择哪种方式主要取决于项目需求和代码风格偏好。希望本文对你在生成带毫秒的时间戳方面有所帮助!

坚韧与成长的2024年

2025-01-01 19:20:35

2024 年,对于我而言,是一段充满挑战与成长的旅程。

从工作中的挫折到家庭的变故,这一年让我更加体会到坚韧的意义,也在风雨中积累了成长的力量。

虽然充满波折,但我仍然选择在逆境中寻找方向,努力让自己变得更加强大。

挑战:逆境的洗礼

在 2024 年中生活与工作的双重挑战交织而来,让我猝不及防。

工作的波折与解脱

其实在去年的年终总结中也提到了,自己已经内耗很久了,而且大部分同事其实也是,职业道路面临着严峻考验,加上大环境不好,工作和家庭多方面带来的压力并不小。

内耗了大概有快一年吧,今年最终也是爆发了:我和一位关系较好的同事一起离职了。

主要原因也是多方面,一是内耗这么久了,不想耗了,世界这么大我想去看看;二是自己的直性格和新同事的背刺;三是公司内部种种事件的发生,使得原本热爱的工作逐渐成为负担。

内耗严重,消耗了我的热情与精力。经过一段时间的挣扎,我决定离开这个让我不再快乐的环境。

离职后的日子可能并不轻松,但也让我重新掌握了生活的主动权,离职后也有听到有几位关系好的同事也先后离开了公司,活成了吃瓜群众...

生活的波澜与坚守

因为房租还未到期,自己也选择了继续在青岛待上一段时间,跟关系好的同事们陆续告别,吃饭喝酒,侃侃而谈,大家也在聊着各自的看法和感受。

离职后,尝试让自己暂时放下压力,为未来的职业方向重新规划,也有疑问为什么不等到过年后再离职?答案还是上面提到的不想耗了,世界这么大我想去看看。

于是我也答应了跟我同一天离职的同事,帮她送兔子去北京,顺便溜达散心,从北京回来之后再起程回老家。

在北京我俩也是喝酒畅聊,还去了一趟雍和宫,在上班和上进之间选择了上香。时间仓促,第三天早上我便出发返程了,不料半路下雨,在出服务区时过了一个小水坑,结果车出现了问题(后来检查得知是电子转向机由于进水坏了),没办法只能一路坚持从高速开回了住处,找了地方维修车辆,避免耽误回老家。

由于转向机突然损坏,不得不承担一笔不小的维修费用,这让本不富裕的家庭雪上加霜,虽然看似是一次小意外,却让我深刻意识到,人生的计划往往会被突如其来的问题打断,我们能做的,是从容面对。

青岛的短暂停留给了我片刻喘息,与老同事的聚会让我感受到人情的温暖。然而,在房租到期后回到老家,奶奶的去世又一次让我面对人生的无常,同时也第一次在医院过夜。

这段时间,我更多地陪伴家人,感悟到亲情的重要性,也开始学会放慢脚步。

就在我努力整理心情,接受上海新工作的同时,命运再次掀起波澜:父亲突然离世,很急很急,我只能在视频中去医院之前见了最后一眼,没想到隔了不到几个小时就得到了人已经走了的消息。

这一噩耗让我深陷悲痛,当晚就请假第二天乘坐最早的飞机回家,奶奶去世时还有父亲在前面撑着,而父亲突然走了,让我手足无措,但我知道我不能垮掉,还有更多的事情在等着我处理。

这个家的生活还要继续,处理完父亲的身后事,直到三七结束,我也重返工作岗位。这段经历不仅考验了我的承受能力,也让我更加清楚地理解了责任的真正含义。

坚韧:在风雨中积累力量

生活和工作的波折让我意识到,坚韧不仅仅是一种态度,更是一种能力。

面对工作中的失落,我学会了取舍,明白了有时候“止损”是对自己最好的成全;面对生活中的离别,我选择直面悲伤,在亲情的回忆中汲取前行的力量。

这一年,尽管前路坎坷,但我始终没有停下脚步。

在适应新的工作节奏中,我不断调整状态,力求用最好的表现迎接挑战。生活的种种考验让我学会了平衡,懂得了如何在压力中找到一丝安慰,让自己变得更坚强、更从容。

成长:收获与前行

2024 年的经历让我深刻体会到,成长往往藏在不经意的每一个瞬间。

离职后的三个月是我重新审视自己的机会,除了本质工作以外,开源事业也是我发自内心热爱的方向。

Docsify 成为 Gitee 成为 GVP 的那一刻,我感受到努力被认可的喜悦,也让我更加坚定地投入到技术与开源社区中。

此外,成为 Apache Answer 的 PPMC Member 也是今年的一大收获。

这份荣誉不仅是一种认可,更是一份责任,促使我不断提升自己,为开源社区贡献更多价值。

无论是在工作还是生活中,我都在这些起起伏伏中找到了成长的契机。

从经历挫折到收获信心,这一年的每一步都让我离更好的自己更近了一些。

展望:迈向崭新的明天

回顾 2024 年,我经历了从失望到解脱,从低谷到重生的全过程。

这些经历让我更加明白,生活并不会因为我们的疲惫而停下脚步,而我们能做的就是在每一次风雨中找到支撑自己的力量。

展望未来,我希望自己能更加沉着应对工作中的挑战,也会投入更多精力到开源社区中,用技术赋能更多人,在社区活动中认识更多人;在生活中,我会更加珍惜与家人、朋友的每一刻,用心感受生活带来的温暖与感动。

这一年让我更加坚信,无论面对什么,只要心中有光,终能走出阴霾。

2025 年,希望是一个充满希望和新机遇的年份,我期待着更多的可能性,也期待着与成长同行,继续前行。

如何使用 Nginx 配置自定义日志并记录用户信息

2024-12-25 10:40:09

在 Web 开发中,日志记录和 HTTP 头部信息的传递非常重要。

Nginx 和 PHP 作为常见的 Web 服务器和处理引擎,结合使用时可以提供强大的日志记录功能和灵活的头部管理。

本文将介绍如何通过 Nginx 配置自定义日志格式、隐藏特定的 HTTP 头信息,并在 PHP 端输出特殊的 Header 信息,以便在 Nginx 日志中记录详细的用户信息。

1. 新增自定义日志格式

通过修改 Nginx 配置,可以定义一个新的日志格式,用于记录详细的用户信息。这个配置将帮助记录 PHP 动态生成的用户信息(如用户 ID、账号等)。

配置步骤

在 Nginx 配置文件中,定义自定义的日志格式,并在访问日志中加入 X-User-Info 头部:

http {
    # 定义自定义日志格式
    log_format custom_log '$remote_addr - $remote_user [$time_local] "$request" '
                           '$status $body_bytes_sent "$http_referer" '
                           '"$http_user_agent" "$http_x_forwarded_for" '
                           '$request_time $upstream_response_time '
                           '$http_x_user_info';  # 记录 X-User-Info 头部信息

    # 使用自定义格式记录日志
    access_log /var/log/nginx/custom_access.log custom_log;
}

在这个配置中:

  • log_format custom_log 定义了日志格式,其中 $http_x_user_info 用来记录通过 HTTP 头传递的用户信息。
  • access_log 指令将日志输出到指定的文件 /var/log/nginx/custom_access.log,并使用定义的 custom_log 格式。

2. 隐藏特定的 HTTP 头信息

在某些情况下,可能不希望某些敏感的 HTTP 头暴露给客户端。Nginx 提供了 proxy_hide_header 指令来隐藏这些头部信息。

此功能特别有用,当需要阻止某些信息(如用户的详细信息)暴露给客户端时。

配置步骤

假设希望隐藏 X-User-Info 头部信息,可以在 location 配置中使用 proxy_hide_header 指令:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend_server;

        # 隐藏 X-User-Info 头部信息
        proxy_hide_header X-User-Info;
    }
}

此配置确保即使 X-User-Info 头部信息在请求中被发送到 Nginx,Nginx 也不会将该头部返回给客户端,从而保护敏感信息。

3. 在 PHP 端输出特殊的 HTTP 头

在 PHP 中,可以动态生成和输出特定的 HTTP 头部信息,并将其传递给 Nginx。比如,在响应头中输出用户信息(如用户 ID、账号等),然后在 Nginx 日志中记录这些信息。

PHP 代码示例

在 PHP 中,可以使用 header() 函数来输出自定义的 HTTP 头。

以下是一个示例,展示如何在 PHP 中生成并发送 X-User-Info 头部信息:

<?php
// 启动会话并获取用户信息
session_start();
$user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 'guest';

// 构造用户信息字符串
$user_info = "user_id={$user_id};";

// 设置 HTTP 头部
header("X-User-Info: {$user_info}");

// 其他 PHP 逻辑...
?>

在这段 PHP 代码中:

  • 通过 session_start() 获取当前用户的 ID(假设它存储在会话中)。如果用户未登录,则默认为 'guest'
  • 获取了用户的 IP 地址、浏览器信息以及当前时间。
  • 使用 header() 函数,将这些信息作为 X-User-Info 头部发送到 Nginx。

4. 结合使用自定义日志格式和隐藏 HTTP 头

在 Nginx 中配置了自定义日志格式,并在 PHP 中输出了 X-User-Info 头部信息。接下来,可以将这两部分结合使用,确保详细的用户信息能够记录到日志中,同时确保这些信息不会暴露给客户端。

完整配置

http {
    # 定义自定义日志格式
    log_format custom_log '$remote_addr - $remote_user [$time_local] "$request" '
                           '$status $body_bytes_sent "$http_referer" '
                           '"$http_user_agent" "$http_x_forwarded_for" '
                           '$request_time $upstream_response_time '
                           '$http_x_user_info';  # 记录 X-User-Info 头部信息

    # 使用自定义格式记录日志
    access_log /var/log/nginx/custom_access.log custom_log;

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://backend_server;

            # 隐藏 X-User-Info 头部信息
            proxy_hide_header X-User-Info;
        }
    }
}

在这个完整配置中:

  • 定义了一个自定义的日志格式 custom_log,其中 $http_x_user_info 用来记录通过 PHP 生成的 X-User-Info 头部。
  • location 块中,使用 proxy_hide_header 隐藏了 X-User-Info 头部,确保敏感信息不会被返回给客户端。

5. 结论

通过结合 Nginx 和 PHP,可以实现以下目标:

  • 详细记录用户信息:通过 X-User-Info 头部将用户的 ID、账号等记录到 Nginx 日志中,便于后续的行为分析和问题排查。
  • 隐藏敏感信息:使用 proxy_hide_header 隐藏特定的 HTTP 头,确保敏感信息不被暴露给客户端。
  • 灵活控制日志内容:通过动态生成 HTTP 头部信息,可以根据需要灵活地定制日志内容,提供更多关于用户行为和请求的详细数据。

这种配置适用于需要详细日志记录的高流量站点,尤其是在需要跟踪用户活动、分析访问模式或保护敏感数据时。

通过合理的日志管理和头部处理,可以在保障系统性能和安全性的同时,提供更丰富的数据支持。

Nginx 配置证书时报错:SSL_CTX_use_PrivateKey failed

2024-12-13 10:20:33

在配置 Nginx SSL 证书时,如果遇到以下错误:

nginx: [emerg] SSL_CTX_use_PrivateKey failed (SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch)

这应该是 SSL 证书和私钥之间的公私钥对不匹配。这篇文章就展开地分析这个问题的原因和解决方案。

错误分析

该错误表示 Nginx 在加载私钥时,检测到证书和私钥之间不匹配。常见原因如下:

  1. 使用了错误的证书文件,如其他域名的证书。
  2. 在配置时不小心选择了错误的私钥文件。
  3. 证书或私钥文件被损坏。
  4. CSR 文件和私钥不匹配。

解决方案

  1. 检查证书和私钥是否匹配

通过 OpenSSL 命令检查证书和私钥的 MD5 值是否匹配:

查看私钥的 MD5 值:

openssl rsa -noout -modulus -in your_private.key | openssl md5

查看证书的 MD5 值:

openssl x509 -noout -modulus -in your_certificate.crt | openssl md5

CSR 的 MD5 值(如果有):

openssl req -noout -modulus -in your_request.csr | openssl md5

如果 MD5 值不匹配,请确保使用了正确的私钥和证书。

  1. 检查私钥是否有效

使用下列命令检查私钥是否有效:

openssl rsa -check -in your_private.key

如果私钥损坏,需重新生成私钥和证书。

  1. 检查证书链是否完整

为了确保证书链完整,可将证书和中间证书合并:

cat your_certificate.crt intermediate_certificate.crt > full_chain.crt

然后在 Nginx 配置文件中指向此合并证书:

ssl_certificate /path/to/full_chain.crt;
ssl_certificate_key /path/to/private.key;
  1. 重新生成 CSR 和私钥

如果不能确保证书和私钥是否一致,可考虑重新生成 CSR 和私钥:

生成新的私钥:

openssl genrsa -out new_private.key 2048

生成 CSR:

openssl req -new -key new_private.key -out new_request.csr

然后将 CSR 提交给 CA (证书授权机构),以获取新证书。

  1. 检查 Nginx 配置

确保配置文件中指向正确的证书和私钥路径,如在 Nginx 中的配置示例:

ssl_certificate /etc/nginx/ssl/full_chain.crt;
ssl_certificate_key /etc/nginx/ssl/private.key;

配置保存后,重启 Nginx:

sudo nginx -t
sudo systemctl reload nginx

这个错误通常是由于证书和私钥不匹配或配置错误导致。通过检查证书和私钥的 MD5 值、检查配置文件和确保证书链完整,可以解决这个问题。

PHP 8.4 发布!

2024-11-20 14:05:13

PHP 8.4 是一个重要的版本,它带来了主要的新功能、对构建依赖项和底层库的几项更新,以及相当多的弃用,以消除旧版 PHP 中一些遗留的不良行为和功能。

它包含许多新功能,例如属性钩子、不对称可见性、更新的 DOM API、性能改进、错误修复和常规清理等。

属性钩子和不对称可见性

PHP 8.4 中最重要的功能之一是新增了 属性钩子 和为 get 和 set 操作分别声明可见性 的功能。

属性钩子

属性钩子允许在访问或设置属性时执行“钩子”逻辑:

class Locale
{
    public string $languageCode;

    public string $countryCode
    {
        set (string $countryCode) {
            $this->countryCode = strtoupper($countryCode);
        }
    }

    public string $combinedCode
    {
        get => \sprintf("%s_%s", $this->languageCode, $this->countryCode);
        set (string $value) {
            [$this->countryCode, $this->languageCode] = explode('_', $value, 2);
        }
    }

    public function __construct(string $languageCode, string $countryCode)
    {
        $this->languageCode = $languageCode;
        $this->countryCode = $countryCode;
    }
}

$brazilianPortuguese = new Locale('pt', 'br');
var_dump($brazilianPortuguese->countryCode); // BR
var_dump($brazilianPortuguese->combinedCode); // pt_BR

非对称可见性

非对称可见性允许为 getset 操作定义不同的作用域:

class PhpVersion
{
    public private(set) string $version = '8.4';
}

$phpVersion = new PhpVersion();
var_dump($phpVersion->version); // string(3) "8.4"
$phpVersion->version = 'PHP 8.3'; // Visibility error

改进的 HTML5 解析器

PHP 8.4 的 DOM 扩展也进行了一次重大功能更新。之前,DOM 扩展仅提供 libxml2 来解析 HTML,而 libxml2 并未跟上 HTML5 的进展。现在,DOM 扩展新增了 Dom\HTMLDocumentDom\XMLDocument 类,其中前者支持 HTML5 合规的解析。

在这一领域有很多新的改进,包括不仅仅是HTML5 解析支持,还包括DOM 规范合规性,以及若干小的增强,比如添加了对 CSS 选择器的支持。

BCMath 扩展新增 Number 类和新函数

PHP 8.4 中的 BCMath 扩展现在支持运算符重载,提供了新的类支持!

use BcMath\Number;

$num1 = new Number('22');
$num2 = new Number('7');
$num3 = new Number('100');

$result = ($num1 / $num2) + $num1 - $num2;
echo $result; // 18.1428571428

现在,不再需要使用 BCMath 函数如 bcaddbcsubbcdiv 等,可以直接使用标准运算符(+-/ 等)。

新的 BcMath\Number 类支持运算符重载,虽然用户自定义 PHP 类尚不支持此功能,但 BCMath 扩展已经实现了这一点,因此可以像使用常规数字一样使用这些对象。

BcMath\Number 类实现了 Stringable 接口,因此这些对象可以在需要字符串的地方使用(比如上例中的 echo 调用)。此外,该类实现了所有的 bc* 函数。例如,还可以调用 $num->add($num2)$num->add('5'),它会返回一个新的 BcMath\Number 对象,而不会修改原始对象,这使得这些对象是不可变的。

新增函数

PDO 驱动特定子类

PDO 驱动特定子类 RFC 已在 PHP 8.4 中实现。它曾在 PHP 8.3 中进行投票,但由于 8.3 的功能冻结,未能实现。

PHP 8.4 现在新增了 Pdo\MysqlPdo\PgsqlPdo\SqlitePdo\DbLibPdo\Firebird 类,这些类扩展了 PDO 类。现在可以在驱动特定子类中使用驱动特定的方法、属性和常量。驱动特定的子类还允许通过只接受/返回驱动特定的子类来使 API 更加明确和限制。

解耦扩展

IMAP、Pspell、OCI8 和 PDO_OCI8 扩展已从 PHP 核心中解耦,现在作为 PECL 扩展提供,用户可以通过 PIE 轻松安装这些扩展。

PHP 发布周期更新

2024 年 4 月,PHP 投票并通过了一项 RFC 提案,以更新 PHP 的发布周期政策。

此前,PHP 核心团队提供两年活跃支持,然后是一年的安全修复支持。

而现在从 PHP 8.1(2021 年 11 月发布)起,所有 PHP 版本将获得 两年安全修复支持,活跃支持期保持两年不变。

此外,活跃支持和生命周期终止(EOL)的日期将调整为日历年的 12 月 31 日,使这些日期更加可预测。

以下是当前 PHP 版本的更新支持和生命周期终止日期,变更部分用加粗标注:

PHP 版本 发布时间 活跃支持至 生命周期终止日期
PHP 8.1 2021-11-25 2023-11-25 2025-12-31
PHP 8.2 2022-12-08 2024-12-31 2026-12-31
PHP 8.3 2023-11-23 2025-12-31 2027-12-31
PHP 8.4 2024-11-21 2026-12-31 2028-12-31
PHP 8.5 2025-11 2027-12-31 2029-12-31

更多信息可以查看 PHP 版本发布页面