发展历史与版本
PHP 诞生于 1995 年,从最初的一个简单工具发展为当今世界上使用最广泛的 Web 编程语言之一。在近三十年的发展历程中,PHP 经历了多次重大版本迭代,每一次都带来了显著的语言改进和性能提升。本节将回顾 PHP 的完整发展历史,并详细介绍从 PHP 8.0 到 PHP 8.4 的核心新特性。
基础概念
PHP 的起源
PHP 的故事始于 1994 年。当时,丹麦籍程序员 Rasmus Lerdorf 用 C 语言编写了一组 Perl CGI 脚本,用来追踪他自己简历的访问者。他将这套脚本命名为 Personal Home Page Tools(个人主页工具),这就是 PHP 最早的名字。
1995 年,Rasmus 将这些脚本重写为 C 语言实现,并开源发布,称为 PHP/FI(Personal Home Page / Forms Interpreter)。PHP/FI 2.0 是第一个公开发布的版本,它已经具备了基本的表单处理、数据库交互和变量使用能力。
版本命名与发布周期
PHP 的版本命名经历了以下演变:
| 时期 | 版本 | 名称含义 |
|---|---|---|
| 1995 | PHP/FI | Personal Home Page / Forms Interpreter |
| 1997 | PHP 3 | PHP: Hypertext Preprocessor(正式确立缩写) |
| 2000 | PHP 4 | 引入 Zend Engine |
| 2004 | PHP 5 | 面向对象编程的重大改进 |
| 2015 | PHP 7 | 性能革命(PHP 6 跳过) |
| 2020 | PHP 8 | 现代化特性(JIT、命名参数、属性等) |
自 PHP 7.0 起,PHP 采用了年度发布的节奏(每年 11 月底或 12 月初发布新版本),每个大版本支持 2 年的活跃更新和 1 年的安全修复。这种节奏使得 PHP 能够持续快速地引入新特性。
详细说明 — 各版本发展历程
PHP/FI(1995-1997)
PHP/FI 是 PHP 的雏形版本,具有以下特征:
- 支持嵌入 HTML 的脚本语法
- 支持基本的表单处理(这是「FI」的由来)
- 支持与 mSQL 数据库的交互
- 支持变量(以
$开头的变量语法从此时确立) - 使用类似 Perl 的语法风格
PHP 3(1998-2000)
PHP 3 是一个里程碑式的版本,由 Zeev Suraski 和 Andi Gutmans 对 PHP/FI 进行了全面重写:
- 全新设计了 PHP 的解析器,执行速度大幅提升
- 正式确立了 PHP: Hypertext Preprocessor 的递归缩写
- 引入了初步的面向对象编程支持(类和对象的基本概念)
- 支持 HTTP Session 管理
- 支持多种数据库(MySQL、PostgreSQL、Oracle 等)
- 引入了扩展 API,使第三方开发者能够编写 PHP 扩展
PHP 4(2000-2005)
PHP 4 引入了 Zend Engine 1.0,这是 PHP 的核心执行引擎:
- Zend Engine 带来了更快的执行速度和更高的稳定性
- 引入了
$_GET、$_POST、$_SESSION等超全局变量 - 支持引用计数(Reference Counting)的内存管理
- 引入了输出缓冲控制(Output Buffering)
- 支持更完善的面向对象特性(构造函数、析构函数)
- 广泛的数据库扩展支持
<?php
declare(strict_types=1);
// PHP 4 时代的典型代码风格
// 注意:这种风格在现代 PHP 中已不推荐
class OldStyle
{
var $name; // var 关键字声明属性(PHP 4 风格,现已弃用)
// PHP 4 构造函数风格(与类同名)
function OldStyle($name)
{
$this->name = $name;
}
function getName()
{
return $this->name;
}
}
// 现代 PHP 等价写法
class ModernStyle
{
public function __construct(
private readonly string $name
) {
}
public function getName(): string
{
return $this->name;
}
}
echo "PHP 4 风格 (已过时):\n";
$old = new OldStyle('PHP 4');
echo "Name: " . $old->getName() . "\n\n";
echo "现代 PHP 风格:\n";
$modern = new ModernStyle('PHP 8');
echo "Name: " . $modern->getName() . "\n";PHP 5(2004-2015)
PHP 5 引入了 Zend Engine 2.0,是 PHP 面向对象编程的一次重大飞跃:
| 特性 | 说明 |
|---|---|
| 访问修饰符 | public、protected、private |
| 抽象类与接口 | 完整的 OOP 支持 |
final 关键字 | 防止类或方法被继承/覆盖 |
| 异常处理 | try/catch/finally |
| SPL(标准 PHP 库) | 迭代器、过滤器等数据结构 |
| PDO(PHP 数据对象) | 统一的数据库访问层 |
| 类型提示 | 函数参数的类型声明(PHP 5.1) |
| 命名空间 | 避免类名冲突(PHP 5.3) |
| 闭包/匿名函数 | 函数式编程支持(PHP 5.3) |
| Trait | 代码复用机制(PHP 5.4) |
| 生成器 | 内存友好的迭代(PHP 5.5) |
| 严格标量类型 | declare(strict_types=1)(PHP 5.6) |
<?php
declare(strict_types=1);
// PHP 5 时代引入的 OOP 特性综合示例
interface Loggable
{
public function getLogMessage(): string;
}
abstract class Entity
{
public function __construct(
protected readonly int $id,
protected readonly string $createdAt
) {
}
abstract public function toArray(): array;
public function getId(): int
{
return $this->id;
}
}
// Trait — PHP 5.4 引入
trait Timestampable
{
protected ?string $updatedAt = null;
public function touch(): void
{
$this->updatedAt = date('Y-m-d H:i:s');
}
public function getUpdatedAt(): ?string
{
return $this->updatedAt;
}
}
// 生成器 — PHP 5.5 引入
class User extends Entity implements Loggable
{
use Timestampable;
public function __construct(
int $id,
string $createdAt,
private readonly string $name,
private readonly string $email
) {
parent::__construct($id, $createdAt);
}
public function getLogMessage(): string
{
return "用户 {$this->name} (ID: {$this->id})";
}
public function toArray(): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'createdAt' => $this->createdAt,
];
}
}
// 使用生成器产生大量数据,内存友好
function generateUserIds(int $count): \Generator
{
for ($i = 1; $i <= $count; $i++) {
yield $i;
}
}
// 演示
$user = new User(1, '2024-01-01', '张三', 'zhangsan@example.com');
$user->touch();
echo $user->getLogMessage() . "\n";
echo "最后更新: " . $user->getUpdatedAt() . "\n";
echo "\n生成器演示 (前 5 个):\n";
foreach (generateUserIds(1000000) as $id) {
echo "ID: {$id}\n";
if ($id >= 5) break;
}PHP 7(2015-2019)
PHP 7 是一次性能和语言的革命性升级,执行速度比 PHP 5.6 快了两倍以上:
| 特性 | 版本 | 说明 |
|---|---|---|
| 性能提升 | 7.0 | Zend Engine 3,性能提升约 2x |
| 标量类型声明 | 7.0 | int、float、string、bool |
| 返回值类型声明 | 7.0 | 函数可以声明返回类型 |
| null 合并运算符 | 7.0 | ?? |
| 太空船运算符 | 7.0 | <=> 三路比较 |
| 匿名类 | 7.0 | 支持创建未命名类 |
Throwable 接口 | 7.0 | 统一的错误/异常处理 |
| 标量返回类型 | 7.1 | void 返回类型 |
| 可空类型 | 7.1 | ?int 等可空类型声明 |
iterable 伪类型 | 7.1 | 可迭代的类型声明 |
| 多异常捕获 | 7.1 | `catch (A |
| 对称数组解构 | 7.1 | [$a, $b] = $array |
| 类型声明强化 | 7.2 | object 类型 |
| 参数类型 widening | 7.2 | 子类参数类型可以更宽松 |
Argon2 密码哈希 | 7.2 | 更安全的密码哈希算法 |
<?php
declare(strict_types=1);
// PHP 7 的核心特性演示
// 标量类型声明 + 返回值类型(PHP 7.0)
function calculateTotal(int $price, int $quantity): int
{
return $price * $quantity;
}
// null 合并运算符(PHP 7.0)
function getConfigValue(array $config, string $key, string $default = 'N/A'): string
{
return $config[$key] ?? $default;
}
// 太空船运算符(PHP 7.0)
function compareVersions(string $a, string $b): int
{
return version_compare($a, $b); // 返回 -1, 0, 1
}
// 可空类型 + void 返回类型(PHP 7.1)
function findUserById(int $id): ?array
{
$users = [
1 => ['id' => 1, 'name' => '张三'],
2 => ['id' => 2, 'name' => '李四'],
];
return $users[$id] ?? null;
}
function logMessage(string $message): void
{
$timestamp = date('Y-m-d H:i:s');
echo "[{$timestamp}] {$message}\n";
}
// 多异常捕获(PHP 7.1)
try {
$result = 10 / 0;
} catch (DivisionByZeroError | ArithmeticError $e) {
logMessage("计算错误: " . $e->getMessage());
}
// 对称数组解构(PHP 7.1)
$coordinates = ['latitude' => 39.9, 'longitude' => 116.4];
['latitude' => $lat, 'longitude' => $lng] = $coordinates;
echo "坐标: {$lat}, {$lng}\n";
// 匿名类(PHP 7.0)
$logger = new class {
public function log(string $message): void
{
echo "[LOG] {$message}\n";
}
};
$logger->log("这是一条匿名类日志");PHP 8(2020 至今)— 现代化新纪元
PHP 8 是 PHP 发展史上又一个重大里程碑版本,引入了 JIT 编译器、命名参数、属性(注解)、联合类型、match 表达式等众多现代语言特性。以下详细介绍 PHP 8.0 到 PHP 8.4 的核心新特性。
PHP 8 各版本核心新特性
PHP 8.0 — 里程碑版本
| 特性 | 说明 |
|---|---|
| JIT(Just-In-Time)编译器 | 将热点函数编译为机器码,显著提升 CPU 密集型任务的性能 |
| 命名参数(Named Arguments) | 通过参数名传值,不再受顺序限制 |
| 联合类型(Union Types) | 类型声明支持多种类型,如 int|float |
| Match 表达式 | 更安全的 switch 替代品 |
| Null 安全运算符 | ?-> 简化 null 检查链 |
| 属性(Attributes) | 原生注解支持,替代 PHPDoc 注解 |
| 构造器属性提升 | 在构造函数中直接声明和初始化属性 |
str_contains() 等新函数 | 更直观的字符串操作函数 |
mixed 类型 | 显式声明混合类型 |
static 返回类型 | 返回值类型声明支持延迟静态绑定 |
WeakMap | 弱引用映射,避免内存泄漏 |
ValueError | 值参数验证异常类 |
<?php
declare(strict_types=1);
// PHP 8.0 新特性演示
// 命名参数
function createUser(
string $name,
string $email,
string $role = 'user',
bool $isActive = true
): array {
return compact('name', 'email', 'role', 'isActive');
}
// 使用命名参数,可以跳过中间的参数
$user = createUser(
email: 'admin@example.com',
name: '管理员',
role: 'admin'
);
print_r($user);
// 联合类型
function parseInput(int|string $input): int
{
if (is_string($input)) {
return (int) filter_var($input, FILTER_SANITIZE_NUMBER_INT);
}
return $input;
}
// Match 表达式
$httpCode = 200;
$statusText = match ($httpCode) {
200, 201, 204 => '成功',
301, 302 => '重定向',
400 => '错误请求',
401 => '未授权',
403 => '禁止访问',
404 => '未找到',
500 => '服务器错误',
default => '未知状态',
};
echo "HTTP {$httpCode}: {$statusText}\n";
// Null 安全运算符
$country = null;
$region = null;
$city = $country?->region?->city ?? '未知城市';
echo "城市: {$city}\n";
// 属性(Attributes)
#[Attribute]
class Route
{
public function __construct(
public readonly string $path,
public readonly string $method = 'GET'
) {
}
}
#[Route(path: '/api/users', method: 'GET')]
function getUsers(): array
{
return ['user1', 'user2', 'user3'];
}
// 构造器属性提升
class Point
{
public function __construct(
public readonly float $x,
public readonly float $y
) {
}
}
$p = new Point(1.5, 2.5);
echo "点坐标: ({$p->x}, {$p->y})\n";
// str_contains 等新字符串函数
$haystack = 'Hello, PHP 8.0!';
echo "包含 'PHP': " . (str_contains($haystack, 'PHP') ? '是' : '否') . "\n";
echo "以 'Hello' 开头: " . (str_starts_with($haystack, 'Hello') ? '是' : '否') . "\n";
echo "以 '!' 结尾: " . (str_ends_with($haystack, '!') ? '是' : '否') . "\n";PHP 8.1 — 枚举与纤程
| 特性 | 说明 |
|---|---|
| 枚举(Enums) | 原生枚举类型,支持接口、方法 |
| 只读属性(Readonly Properties) | 属性只能初始化一次 |
| 纤程(Fibers) | 协程/轻量级线程支持 |
| 交集类型(Intersection Types) | 类型声明支持多类型交集,如 A&B |
never 返回类型 | 表示函数永不返回 |
final 类的常量 | final 类中可以声明常量 |
新的 readonly 转为属性 | — |
array_is_list() | 检查数组是否是 0-indexed 列表 |
fsync()/fdatasync() | 文件同步函数 |
<?php
declare(strict_types=1);
// PHP 8.1 新特性演示
// 枚举(Enums)
enum HttpMethod: string
{
case Get = 'GET';
case Post = 'POST';
case Put = 'PUT';
case Delete = 'DELETE';
case Patch = 'PATCH';
public function isSafe(): bool
{
return match ($this) {
self::Get, self::Head => true,
default => false,
};
}
public function description(): string
{
return match ($this) {
self::Get => '获取资源',
self::Post => '创建资源',
self::Put => '更新资源',
self::Delete => '删除资源',
self::Patch => '部分更新',
};
}
}
$method = HttpMethod::Get;
echo "方法: {$method->value}\n";
echo "安全: " . ($method->isSafe() ? '是' : '否') . "\n";
echo "描述: {$method->description()}\n";
// 只读属性
class Configuration
{
public function __construct(
public readonly string $appName,
public readonly string $appEnv,
public readonly bool $debug,
public readonly int $port = 8080
) {
}
}
$config = new Configuration('MyApp', 'production', false, 443);
echo "应用: {$config->appName} ({$config->appEnv})\n";
// 交集类型
interface CountableContainer
{
public function count(): int;
}
interface IteratorAggregate
{
public function getIterator(): \ArrayIterator;
}
class Collection implements CountableContainer, IteratorAggregate
{
private array $items = [];
public function add(string $item): void
{
$this->items[] = $item;
}
public function count(): int
{
return count($this->items);
}
public function getIterator(): \ArrayIterator
{
return new \ArrayIterator($this->items);
}
}
// never 返回类型 — 表示函数绝不正常返回
function handleNotFound(): never
{
http_response_code(404);
echo '<h1>404 Not Found</h1>';
exit;
}
// array_is_list
$arr1 = ['a', 'b', 'c'];
$arr2 = [0 => 'a', 1 => 'b', 2 => 'c'];
$arr3 = [0 => 'a', 2 => 'b']; // 跳过了索引 1
echo "arr1 是列表: " . (array_is_list($arr1) ? '是' : '否') . "\n";
echo "arr2 是列表: " . (array_is_list($arr2) ? '是' : '否') . "\n";
echo "arr3 是列表: " . (array_is_list($arr3) ? '是' : '否') . "\n";PHP 8.2 — 只读类与析构嵌套
| 特性 | 说明 |
|---|---|
| 只读类(Readonly Classes) | 整个类的所有属性都是只读的 |
| 析构嵌套(DNF Types) | 组合联合类型和交集类型,如 (A&B)|C |
参数中的 ... 展示 | 可以将命名参数传递给可变参数函数 |
#[\AllowDynamicProperties] | 标注允许动态属性的类 |
#[\SensitiveParameter] | 敏感参数不会出现在堆栈跟踪中 |
| 新的随机数扩展 | 对象化的随机数生成器 |
odometer trait 弃用 | — |
| trait 中的常量 | Trait 中可以定义常量 |
<?php
declare(strict_types=1);
// PHP 8.2 新特性演示
// 只读类
readonly class DtoUser
{
public function __construct(
public string $name,
public string $email,
public int $age
) {
}
}
$userDto = new DtoUser('张三', 'zhangsan@example.com', 30);
echo "用户: {$userDto->name}, 年龄: {$userDto->age}\n";
// DNF 类型 (Disjunctive Normal Form Types)
function processResource(string|array|int $input): string
{
if (is_string($input)) {
return "字符串: {$input}";
}
if (is_int($input)) {
return "整数: {$input}";
}
if (is_array($input)) {
return "数组: " . json_encode($input, JSON_UNESCAPED_UNICODE);
}
return "未知类型";
}
echo processResource("hello") . "\n";
echo processResource(42) . "\n";
echo processResource(['key' => 'value']) . "\n";
// 新的随机数扩展
use Random\Randomizer;
$randomizer = new Randomizer();
// 生成随机整数
$randomInt = $randomizer->getInt(1, 100);
echo "随机整数 (1-100): {$randomInt}\n";
// 从数组中随机选择一个元素
$options = ['苹果', '香蕉', '橙子', '葡萄'];
$fruit = $randomizer->pickArrayValues($options, 1);
echo "随机水果: {$fruit[0]}\n";
// 生成随机字节(适合生成密码/令牌)
$bytes = $randomizer->getBytes(16);
$token = bin2hex($bytes);
echo "随机令牌: {$token}\n";
// 敏感参数 — 在堆栈跟踪中隐藏
function connectToDatabase(
string $host,
string $username,
#[\SensitiveParameter]
string $password
): void
{
echo "连接到 {$host} 用户 {$username}\n";
// password 不会出现在错误堆栈中
}PHP 8.3 — 类型化类常量与改进
| 特性 | 说明 |
|---|---|
| 类型化类常量 | 类常量可以声明类型 |
| 动态类常量获取 | Foo::{$bar} 语法 |
#[\Override] 属性 | 标明方法覆盖了父类方法 |
json_validate() | 验证字符串是否为有效的 JSON |
新的 Random 方法 | getBytesFromString() 等 |
clone 操作符可用 readonly | — |
| 堆栈跟踪改进 | 更详细的错误堆栈信息 |
<?php
declare(strict_types=1);
// PHP 8.3 新特性演示
// 类型化类常量
class ApiVersion
{
public const string V1 = 'v1';
public const string V2 = 'v2';
public const int MAX_ITEMS = 100;
public const string CURRENT = self::V2;
}
echo "当前 API 版本: " . ApiVersion::CURRENT . "\n";
echo "最大条目数: " . ApiVersion::MAX_ITEMS . "\n";
// 动态类常量获取
class Status
{
public const ACTIVE = 'active';
public const INACTIVE = 'inactive';
public const PENDING = 'pending';
}
$statusField = 'ACTIVE';
$statusCode = Status::{$statusField};
echo "状态: {$statusCode}\n";
// json_validate() — PHP 8.3 新增
$jsonStrings = [
'{"name": "张三", "age": 30}',
'{"name": "李四", "age": }', // 无效 JSON
'not json at all',
];
foreach ($jsonStrings as $json) {
$isValid = json_validate($json);
echo "JSON 有效: " . ($isValid ? '是' : '否') . " — {$json}\n";
}
// #[\Override] 属性
abstract class BaseService
{
public function initialize(): void
{
echo "BaseService 初始化\n";
}
public function process(): string
{
return 'base process';
}
}
class UserService extends BaseService
{
#[\Override]
public function initialize(): void
{
echo "UserService 初始化\n";
parent::initialize();
}
#[\Override]
public function process(): string
{
return 'user process';
}
}
$service = new UserService();
$service->initialize();
echo "处理结果: " . $service->process() . "\n";PHP 8.4 — 属性钩子与新的数组函数
| 特性 | 说明 |
|---|---|
| 属性钩子(Property Hooks) | __get/__set 的语法糖,更优雅的属性访问控制 |
| Asymmetric Visibility | 不对称可见性,如 public private(set) |
| 新的数组函数 | array_find()、array_find_key()、array_any()、array_all() |
带闭包的 new 表达式 | new Foo(function() {}) |
parse_url() 改进 | 返回组件数组而非 null |
html_entity_decode() 改进 | — |
mb_str_pad() | — |
<?php
declare(strict_types=1);
// PHP 8.4 新特性演示
// 属性钩子(Property Hooks)
class Temperature
{
public float $celsius {
get {
return $this->_celsius;
}
set(float $value) {
if ($value < -273.15) {
throw new \ValueError('温度不能低于绝对零度 (-273.15 C)');
}
$this->_celsius = $value;
}
}
// 虚拟属性(无后备字段)
public float $fahrenheit {
get => $this->_celsius * 9 / 5 + 32;
set => $this->_celsius = ($value - 32) * 5 / 9;
}
private float $_celsius = 0.0;
public function __construct(float $celsius = 0.0)
{
$this->_celsius = $celsius;
}
}
// 注意:属性钩子目前仅作为示例展示 PHP 8.4 的特性
echo "=== PHP 8.4 新特性 ===\n";
echo "属性钩子允许为属性定义自定义的 get/set 行为\n";
// 不对称可见性(PHP 8.4)
class BankAccount
{
// 外部可读,只能内部写入
public string $accountNumber {
public readonly get => $this->_accountNumber;
}
public float $balance {
public get => $this->_balance;
private set => $this->_balance = $value;
}
private string $_accountNumber;
private float $_balance = 0.0;
public function __construct(string $accountNumber)
{
$this->_accountNumber = $accountNumber;
}
public function deposit(float $amount): void
{
if ($amount <= 0) {
throw new \ValueError('存款金额必须大于 0');
}
$this->_balance += $amount;
}
public function withdraw(float $amount): void
{
if ($amount <= 0) {
throw new \ValueError('取款金额必须大于 0');
}
if ($amount > $this->_balance) {
throw new \ValueError('余额不足');
}
$this->_balance -= $amount;
}
}
echo "不对称可见性: 外部可读 private(set)\n";
// 新的数组函数(PHP 8.4)
$users = [
['id' => 1, 'name' => '张三', 'role' => 'admin'],
['id' => 2, 'name' => '李四', 'role' => 'user'],
['id' => 3, 'name' => '王五', 'role' => 'admin'],
['id' => 4, 'name' => '赵六', 'role' => 'user'],
];
// array_find — 查找第一个匹配的元素
$admin = array_find($users, fn($u) => $u['role'] === 'admin');
echo "第一个管理员: " . ($admin['name'] ?? '未找到') . "\n";
// array_find_key — 查找第一个匹配的键
$adminKey = array_find_key($users, fn($u) => $u['role'] === 'admin');
echo "管理员键名: {$adminKey}\n";
// array_any — 是否有任何元素满足条件
$hasAdmin = array_any($users, fn($u) => $u['role'] === 'admin');
echo "有管理员: " . ($hasAdmin ? '是' : '否') . "\n";
// array_all — 是否所有元素都满足条件
$allActive = array_all($users, fn($u) => isset($u['name']));
echo "全部有效: " . ($allActive ? '是' : '否') . "\n";PHP 8.x 版本特性速查表
| 特性 | PHP 8.0 | PHP 8.1 | PHP 8.2 | PHP 8.3 | PHP 8.4 |
|---|---|---|---|---|---|
| JIT 编译器 | Yes | - | - | - | - |
| 命名参数 | Yes | - | - | - | - |
| 联合类型 | Yes | - | - | - | - |
| Match 表达式 | Yes | - | - | - | - |
| Null 安全运算符 | Yes | - | - | - | - |
| 属性(Attributes) | Yes | - | - | - | - |
| 构造器属性提升 | Yes | - | - | - | - |
str_contains 等 | Yes | - | - | - | - |
| 枚举 | - | Yes | - | - | - |
| 只读属性 | - | Yes | - | - | - |
| 纤程(Fibers) | - | Yes | - | - | - |
| 交集类型 | - | Yes | - | - | - |
never 返回类型 | - | Yes | - | - | - |
| 只读类 | - | - | Yes | - | - |
| DNF 类型 | - | - | Yes | - | - |
| 新随机数扩展 | - | - | Yes | - | - |
| 敏感参数 | - | - | Yes | - | - |
| 类型化类常量 | - | - | - | Yes | - |
json_validate | - | - | - | Yes | - |
#[\Override] | - | - | - | Yes | - |
| 属性钩子 | - | - | - | - | Yes |
| 不对称可见性 | - | - | - | - | Yes |
array_find 等新函数 | - | - | - | - | Yes |
当前版本选择建议
生产环境推荐
版本推荐(截至 2026 年)
- 首选推荐:PHP 8.3 LTS(长期支持)
- 次选:PHP 8.2(稳定)
- 尝鲜:PHP 8.4(最新)
版本生命周期
PHP 的版本支持周期如下:
| 版本 | 发布日期 | 活跃支持截止 | 安全支持截止 | 状态 |
|---|---|---|---|---|
| PHP 8.1 | 2021-11 | 2023-11 | 2024-12 | 安全修复结束 |
| PHP 8.2 | 2022-12 | 2024-12 | 2025-12 | 安全修复中 |
| PHP 8.3 | 2023-11 | 2025-11 | 2026-12 | 活跃支持中 |
| PHP 8.4 | 2024-11 | 2026-11 | 2027-12 | 活跃支持中 |
版本选择原则
<?php
declare(strict_types=1);
// 版本选择建议工具
class VersionRecommender
{
public function recommend(string $scenario): string
{
return match ($scenario) {
'new-project' => 'PHP 8.3+ — 新项目建议使用最新的稳定版本',
'legacy-project' => '至少升级到 PHP 8.1 — 最低要求',
'production' => 'PHP 8.3 LTS — 生产环境推荐使用 LTS 版本',
'learning' => 'PHP 8.3 — 学习时使用最新稳定版,体验全部新特性',
'high-performance' => 'PHP 8.3+ with JIT — 启用 JIT 以获得最佳性能',
'shared-hosting' => '取决于主机支持的版本,最低 PHP 8.1',
default => 'PHP 8.3 — 通用推荐',
};
}
public function checkPhpVersion(): array
{
$versionId = PHP_VERSION_ID;
if ($versionId < 80100) {
return [
'status' => 'unsupported',
'message' => "PHP " . PHP_VERSION . " 已不再受支持,请立即升级到 PHP 8.1+",
'recommended' => '8.3',
];
}
if ($versionId < 80200) {
return [
'status' => 'eol',
'message' => "PHP " . PHP_VERSION . " 已结束安全支持",
'recommended' => '8.3',
];
}
return [
'status' => 'supported',
'message' => "PHP " . PHP_VERSION . " 受到支持",
'recommended' => '8.3',
];
}
}
$recommender = new VersionRecommender();
// 输出当前 PHP 版本检查结果
$check = $recommender->checkPhpVersion();
echo "=== PHP 版本检查 ===\n";
echo "当前版本: " . PHP_VERSION . " (ID: " . PHP_VERSION_ID . ")\n";
echo "状态: {$check['status']}\n";
echo "建议: {$check['message']}\n";实战示例
PHP 版本特性检测工具
<?php
declare(strict_types=1);
/**
* PHP 版本特性检测工具
* 检测当前 PHP 版本支持哪些特性
*/
class FeatureDetector
{
private array $features = [];
public function __construct()
{
$this->features = [
'named_args' => [
'min_version' => '8.0',
'name' => '命名参数',
'check' => fn(): bool => PHP_VERSION_ID >= 80000,
],
'union_types' => [
'min_version' => '8.0',
'name' => '联合类型',
'check' => fn(): bool => PHP_VERSION_ID >= 80000,
],
'match' => [
'min_version' => '8.0',
'name' => 'Match 表达式',
'check' => fn(): bool => PHP_VERSION_ID >= 80000,
],
'attributes' => [
'min_version' => '8.0',
'name' => '属性(Attributes)',
'check' => fn(): bool => PHP_VERSION_ID >= 80000,
],
'constructor_promotion' => [
'min_version' => '8.0',
'name' => '构造器属性提升',
'check' => fn(): bool => PHP_VERSION_ID >= 80000,
],
'null_safe_operator' => [
'min_version' => '8.0',
'name' => 'Null 安全运算符',
'check' => fn(): bool => PHP_VERSION_ID >= 80000,
],
'fibers' => [
'min_version' => '8.1',
'name' => '纤程(Fibers)',
'check' => fn(): bool => PHP_VERSION_ID >= 80100,
],
'enums' => [
'min_version' => '8.1',
'name' => '枚举(Enums)',
'check' => fn(): bool => PHP_VERSION_ID >= 80100,
],
'readonly_props' => [
'min_version' => '8.1',
'name' => '只读属性',
'check' => fn(): bool => PHP_VERSION_ID >= 80100,
],
'intersection_types' => [
'min_version' => '8.1',
'name' => '交集类型',
'check' => fn(): bool => PHP_VERSION_ID >= 80100,
],
'readonly_classes' => [
'min_version' => '8.2',
'name' => '只读类',
'check' => fn(): bool => PHP_VERSION_ID >= 80200,
],
'dnf_types' => [
'min_version' => '8.2',
'name' => 'DNF 类型',
'check' => fn(): bool => PHP_VERSION_ID >= 80200,
],
'json_validate' => [
'min_version' => '8.3',
'name' => 'json_validate()',
'check' => fn(): bool => PHP_VERSION_ID >= 80300,
],
'typed_constants' => [
'min_version' => '8.3',
'name' => '类型化类常量',
'check' => fn(): bool => PHP_VERSION_ID >= 80300,
],
'property_hooks' => [
'min_version' => '8.4',
'name' => '属性钩子',
'check' => fn(): bool => PHP_VERSION_ID >= 80400,
],
'asymmetric_visibility' => [
'min_version' => '8.4',
'name' => '不对称可见性',
'check' => fn(): bool => PHP_VERSION_ID >= 80400,
],
];
}
public function checkAll(): void
{
echo "PHP " . PHP_VERSION . " 特性支持检测\n";
echo str_repeat('-', 50) . "\n";
$supported = 0;
$unsupported = 0;
foreach ($this->features as $key => $feature) {
$isSupported = ($feature['check'])();
$status = $isSupported ? 'OK' : 'X';
$version = $feature['min_version'];
echo sprintf(
" [%s] %-25s (PHP %s)\n",
$status,
$feature['name'],
$version
);
if ($isSupported) {
$supported++;
} else {
$unsupported++;
}
}
echo str_repeat('-', 50) . "\n";
echo "支持: {$supported} / 不支持: {$unsupported}\n";
}
}
$detector = new FeatureDetector();
$detector->checkAll();注意事项
- PHP 6 被跳过:PHP 6 的开发计划因 Unicode 支持的复杂性而被放弃,为了避免与 Unicode 项目混淆,PHP 直接从 5 跳到了 7。这也是为什么不存在 PHP 6 版本。
- 不要使用已 EOL 的版本:PHP 7.4 及更早版本已经停止支持,不再接收安全更新。继续使用这些版本存在安全风险。
- 迁移需谨慎:从旧版本升级到新版本前,务必使用兼容性检查工具(如 PHP Compatibility Checker)扫描代码。
- 扩展兼容性:升级 PHP 版本时,部分第三方扩展可能尚未适配新版本,需要提前确认。
- 框架版本要求:主流 PHP 框架有其最低版本要求。例如,Laravel 11 要求 PHP 8.2+。
最佳实践
- 始终使用受支持的 PHP 版本,优先选择当前活跃支持的版本。
- 在
composer.json中指定 PHP 版本的最低要求:"php": "^8.1"。 - 在 CI/CD 流水线中测试多个 PHP 版本,确保兼容性。
- 关注 PHP RFC(Request for Comments)页面,提前了解即将引入的新特性。
- 升级时使用渐进式策略:先在开发环境测试,再逐步推广到生产环境。
- 使用 PHP 原生特性(如枚举、只读属性)替代自定义实现,减少代码复杂度。
下一节
了解了 PHP 的发展历史和版本特性之后,让我们开始动手实践。下一节 基础交互脚本 将带你编写第一个 PHP 脚本。