php 8中类属性默认值必须为常量表达式:标量、数组字面量、null/true/false、类/全局常量;禁止运行时计算如函数调用、new对象、超全局变量;readonly属性(php 8.3+)同理,且实例化后不可修改。

PHP 8 中自定义类属性的默认值写法,核心原则是:**必须为常量表达式,不能含运行时计算逻辑**。无论是普通属性还是只读(readonly)属性,都遵循这一底层限制。
普通属性默认值怎么设
PHP 7.4+ 支持在声明属性时直接赋值,但仅限以下类型:
- 标量值:
public string $status = 'pending'; - 布尔/整数/浮点:
protected bool $active = true;、private int $retry = 3; - 数组字面量:
public array $roles = ['user', 'guest']; - null、true、false 等字面量:
public ?string $note = null; - 类常量或全局常量:
public string $env = APP_ENV;或public string $mode = self::MODE_DEV;
以下写法会报错:public string $now = date('Y-m-d');、public Logger $logger = new Logger();、public string $path = $_SERVER['DOCUMENT_ROOT'];——这些都属于运行时表达式,PHP 编译期无法解析。
只读属性(readonly)默认值写法(PHP 8.3+)
PHP 8.3 新增能力:readonly 属性也可带默认值,语义更清晰,适用 DTO、配置类等场景。
- 合法示例:
public readonly string $format = 'json'; - 支持嵌套数组:
public readonly array $headers = ['Content-Type' => 'application/json']; - 可与构造函数配合:
public readonly int $timeout = 30;,若构造函数中写了$this->timeout = $custom;,则覆盖默认值;否则保留 30
注意:一旦对象实例化完成,该属性值不可再修改,否则抛出 Fatal error: Cannot modify readonly property。
类型声明 + 默认值的组合规则
PHP 8 开始广泛支持属性类型声明,搭配默认值需注意兼容性:
- 类型必须能容纳默认值:
public string $name = 'anon';✅,但public string $name = null;❌(null 不属于 string) - 如需允许 null,必须用可空类型:
public ?string $name = null;✅ - 联合类型也支持:
public string|int $id = 'default';✅ - 数组类型写法:
public array $data = [];✅,public array $data = null;❌(除非声明为?array)
哪些写法看起来合理但实际非法
常见误用,编译阶段即报错:
-
public string $token = generateToken();—— 函数调用不被允许 -
public array $config = parse_ini_file('app.ini');—— 运行时 I/O 操作 -
public string $host = getenv('DB_HOST');—— 超全局变量非编译时常量 -
public User $user = new User();—— 对象实例化(PHP 8.1+ 允许在函数参数中 new,但类属性仍禁止)
动态初始化请移至 __construct() 中处理:$this->user = new User();。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











