本文目录导读:

- 冻结变量/对象(使其不可修改)
- 冻结变量(防止在全局/函数中意外修改)
- 序列化/反序列化时的“冻结”(防止修改已有对象)
- 冻结时间/日期(DateTimeImmutable)
- 如果你是指“冻结”代码执行(暂停/等待)
- 最可能需要的三种情况
在 PHP 中,“冻结”这个概念通常有以下几种不同的含义,具体取决于你想实现什么目的,我来逐一解释最可能的情况:
冻结变量/对象(使其不可修改)
PHP 没有像 Java 的 final 或 JS 的 Object.freeze() 那样的原生关键字,但可以通过以下几种方式模拟:
方式 A:使用只读属性(PHP 8.1+)
class FrozenObject {
public function __construct(
public readonly string $name, // 初始化后不可修改
public readonly int $age
) {}
}
$obj = new FrozenObject("Alice", 30);
// $obj->name = "Bob"; // 会报错:Cannot modify readonly property
方式 B:使用私有属性 + 无 setter
class Config {
private array $settings;
public function __construct(array $settings) {
$this->settings = $settings;
}
public function get(string $key): mixed {
return $this->settings[$key] ?? null;
}
// 故意不提供修改方法
}
方式 C:使用 __set 魔术方法阻止写入
class Frozen {
private array $data = [];
public function __set($name, $value) {
throw new \RuntimeException("Object is frozen, cannot set $name");
}
}
冻结变量(防止在全局/函数中意外修改)
如果是指“冻结”某个普通变量(非对象),PHP 没有直接支持,但可以用 引用 + 只读类 来间接实现:
$config = new readonly class(['db_host' => 'localhost']) {
public function __construct(public array $settings) {}
};
// $config->settings['db_host'] = 'other'; // 不允许
序列化/反序列化时的“冻结”(防止修改已有对象)
有时“冻结”指将对象转为持久化状态(如存入缓存),后续只能读取:
$obj = new stdClass();
$obj->status = "active";
// “冻结”为字符串(序列化)
$frozen = serialize($obj); // 或者 json_encode
file_put_contents('cache.txt', $frozen);
// 解冻
$unfrozen = unserialize(file_get_contents('cache.txt'));
冻结时间/日期(DateTimeImmutable)
如果是指日期时间的“冻结”:
$date = new DateTimeImmutable("2024-01-01");
// 所有修改方法返回新对象,原对象不变
$modified = $date->modify("+1 day");
echo $date->format('Y-m-d'); // 2024-01-01(原始不变)
echo $modified->format('Y-m-d'); // 2024-01-02
如果你是指“冻结”代码执行(暂停/等待)
这种情况较少见,但可以用 sleep() 或 Swoole 协程的 go() + sleep():
echo "开始"; sleep(5); // 冻结5秒 echo "结束";
最可能需要的三种情况
| 你真正的需求 | 解决方案 |
|---|---|
| 防止对象属性被修改 | readonly 属性(PHP 8.1+) 或 私有属性 + 无 setter |
| 防止全局变量被意外改 | 使用 define() 常量 或 只读类封装 |
| 保存对象状态到文件/缓存 | serialize() / json_encode() |
如果想实现类似 JS Object.freeze() 的完全不可变: PHP 没有原生等价物,最接近的是 readonly class(PHP 8.2+)或在构造函数中一次性设置所有属性。
如果你能补充具体场景(想防止用户在类外部修改某个属性”或“想缓存一个对象”),我可以给出更精准的代码示例。