PHP 8.3 新特性
PHP 8.3 引入了类常量类型声明、动态类常量获取(动态类名访问常量)、json_validate() 函数、#[Override] 属性、深度克隆只读属性等特性。这些改进增强了类型安全性和开发便利性。
前置知识
阅读本节前,建议先了解:PHP 8.2 新特性
类常量类型声明
基本用法
php
<?php
declare(strict_types=1);
// PHP 8.3+ 支持类常量的类型声明
class PaymentGateway
{
// 类型化的类常量
public const string MODE_LIVE = 'live';
public const string MODE_TEST = 'test';
public const int MAX_RETRY = 3;
public const float TAX_RATE = 0.13;
public const bool DEBUG = false;
public const array SUPPORTED_CURRENCIES = ['USD', 'EUR', 'CNY'];
public const string API_VERSION = 'v2';
// 接口常量也可以有类型
final public const string DEFAULT_ENV = 'production';
}
// 枚举常量也支持类型(之前已支持,现在强化)
enum HttpStatus: int
{
public const int OK_MIN = 200;
public const int OK_MAX = 299;
public const int ERROR_MIN = 400;
case Ok = 200;
case NotFound = 404;
case ServerError = 500;
}接口与 trait 中的常量类型
php
<?php
declare(strict_types=1);
interface Cacheable
{
public const string CACHE_PREFIX = 'cache_';
public const int DEFAULT_TTL = 3600;
}
trait HasVersion
{
public const string VERSION_FIELD = 'version';
public const int MAX_VERSIONS = 100;
}
class Document implements Cacheable
{
use HasVersion;
}常量类型限制
类常量的类型声明支持:string、int、float、bool、array。不支持 void、null、callable、object 等类型。
动态类常量获取
php
<?php
declare(strict_types=1);
// PHP 8.3+ 支持通过变量访问类常量
class Config
{
public const string DB_HOST = 'localhost';
public const string DB_PORT = '3306';
public const string DB_NAME = 'myapp';
}
// 通过变量获取常量
$field = 'DB_HOST';
echo Config::{$field}; // "localhost"
// 动态获取
function getConstant(string $class, string $constant): mixed
{
return $class::{$constant};
}
echo getConstant(Config::class, 'DB_HOST'); // "localhost"
echo getConstant(Config::class, 'DB_PORT'); // "3306"
// 与枚举配合
enum Status: string
{
case Active = 'active';
case Inactive = 'inactive';
}
$caseName = 'Active';
$status = Status::{$caseName}; // Status::Active
echo $status->value; // "active"json_validate() 函数
php
<?php
declare(strict_types=1);
// PHP 8.3+ json_validate() 验证字符串是否为合法 JSON
// 基本用法
json_validate('{"name":"John"}'); // true
json_validate('{"name": "John"}'); // true
json_validate('invalid json'); // false
json_validate('{"name": }'); // false(语法错误)
json_validate(''); // false
// 实际应用
function parseJsonRequest(string $body): array
{
if (!json_validate($body)) {
throw new InvalidArgumentException('Invalid JSON format');
}
$data = json_decode($body, true);
if ($data === null) {
throw new InvalidArgumentException('JSON decode failed');
}
return $data;
}
// 深度限制验证(PHP 8.3+)
json_validate('{"deep": ' . str_repeat('[', 512) . '}', depth: 512);json_validate vs json_decode
json_validate() 比 json_decode() + json_last_error() 更快,因为它只验证不解析。适合在解析前做快速检查。
Override 属性
php
<?php
declare(strict_types=1);
use Override;
// PHP 8.3+ #[Override] 属性
// 当方法声明 override 父类方法时,PHP 会验证父类确实有该方法
// 如果父类没有该方法,会产生编译时错误
abstract class BaseService
{
abstract public function validate(array $data): bool;
abstract public function process(array $data): void;
public function log(string $message): void
{
echo "[LOG] {$message}\n";
}
}
class UserService extends BaseService
{
#[Override] // 确保父类有 validate 方法
public function validate(array $data): bool
{
return isset($data['email']);
}
#[Override] // 确保父类有 process 方法
public function process(array $data): void
{
echo "Processing user: {$data['email']}\n";
}
#[Override] // 确保父类有 log 方法
public function log(string $message): void
{
echo "[USER LOG] {$message}\n";
}
// ❌ 如果误写方法名,#[Override] 会在编译时报错
// #[Override]
// public function proces(array $data): void {} // Error: No method to override
}深度克隆只读属性
php
<?php
declare(strict_types=1);
// PHP 8.3+ 允许在 __clone() 中修改 readonly 属性
readonly class Address
{
public function __construct(
public string $street,
public string $city,
public string $country,
) {}
}
readonly class User
{
public function __construct(
public string $name,
public Address $address,
) {}
// PHP 8.3+ 可以在 __clone 中修改 readonly 属性
public function __clone()
{
$this->address = clone $this->address;
// 之前不能这样做,因为 address 是 readonly
}
}
$original = new User(
name: 'John',
address: new Address('123 Main St', 'New York', 'US'),
);
$clone = clone $original;
$clone->name = 'Jane'; // ❌ 仍然不能修改(readonly)其他改进
方法参数的匿名类
php
<?php
declare(strict_types=1);
// PHP 8.3+ 允许创建匿名类实例作为参数
$collection = collect([1, 2, 3])
->filter(fn (int $item) => $item > 1)
->map(fn (int $item) => $item * 2);获取类名方法改进
php
<?php
declare(strict_types=1);
// PHP 8.3+ 可以获取匿名类的类名
$class = new class {};
echo $class::class; // class@anonymous /path/to/file.php:line
// 新增方法
$obj = new stdClass();
$className = $obj::class; // "stdClass"最佳实践
- 使用类常量类型:为类常量添加类型声明,提升类型安全
- 使用 #[Override]:防止方法签名不匹配导致的隐含 Bug
- 使用 json_validate():在 json_decode 前做快速验证
- 利用动态常量获取:减少反射使用,简化动态访问代码
下一节
继续学习:PHP 8.4 新特性