__construct 和 __destruct 是对象生命周期的起点与终点,但需注意:反序列化不触发 __construct,子类须显式调用父构造函数;__destruct 触发时机不可控且不保证执行,子类也需手动调用父析构函数;二者应轻量、无副作用,避免业务逻辑与外部交互。

__construct 和 __destruct 是对象生命周期的起点与终点,但它们的触发时机、继承行为和副作用控制,稍不注意就会埋下隐患。
__construct 不会在反序列化时执行
这是最容易被忽略的关键点:用 unserialize() 恢复对象时,__construct 完全不会被调用。对象是“重建”而非“新建”,所有属性直接从数据中还原。
- 如果构造函数里做了关键初始化(比如加载配置、建立数据库连接),反序列化后的对象可能处于无效状态
- 需要在 __wakeup() 或 __unserialize() 中补全这些逻辑
- 不要在构造函数中假设“每次对象出现都经过了这里”
子类必须显式调用 parent::__construct()
只要子类定义了自己的 __construct,父类的构造逻辑就不会自动执行——PHP 不会隐式调用父构造函数。
- 遗漏 parent::__construct() 会导致父类属性未初始化、依赖未注入、前置检查被跳过
- 如果父类构造函数有参数,子类调用时必须传入对应值,否则报错
- 若子类没定义构造函数,则自动继承父类的(前提是父类构造函数不是 private)
__destruct 的触发时机不可控且不保证执行
析构函数在对象被销毁时调用,但这个“销毁”由 PHP 垃圾回收器决定,不是立即、确定或可预测的。
- 不能依赖它做关键清理(如释放锁、提交事务),因为可能延迟很久甚至不执行(如脚本异常终止)
- 不要在 __destruct 中抛出异常,PHP 会静默忽略,且可能干扰 GC
- 子类若定义了 __destruct,也需手动调用 parent::__destruct(),否则父类清理逻辑丢失
避免在两个方法中引入副作用
构造和析构函数应保持“轻量”和“可预测”。它们不是业务入口,而是状态管理节点。
- __construct 中避免发邮件、写日志文件、调用外部 API —— 这些应抽离到独立方法(如 init() 或 connect())
- __destruct 中避免阻塞操作(如等待网络响应)、复杂计算或重新打开已关闭资源
- 两者都不适合处理用户输入或执行权限校验,这类逻辑应在业务方法中明确控制
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











