__construct 必须定义在类中且为public,仅在new时由引擎自动调用;不支持重载,子类需显式调用parent::__construct()并传参;应避免耗时操作、用类型声明和默认值保障安全,非法状态应抛异常而非返回错误标识。

__construct 必须定义在类里,不能单独调用
PHP 的 __construct 是魔术方法,只在 new 实例化时由引擎自动触发,你手动写 $obj->__construct() 不会报错但毫无意义——它只是个普通方法调用,不会触发对象初始化逻辑,也不会影响对象生命周期。
常见错误现象:有人把构造逻辑写进普通方法(比如 init()),再在外部反复调用,结果属性状态混乱、依赖未建立、甚至出现 Notice: Undefined property。
- 构造函数必须声明为
public,否则new会失败(PHP 8.0+ 直接 Fatal error) - 类中没定义
__construct,PHP 会静默使用空的默认构造函数;一旦定义,就完全覆盖默认行为 - 不支持重载:不能有多个
__construct方法,也不能靠参数类型/数量不同来区分
子类继承时 parent::__construct() 不是可选项
如果父类有 __construct 且做了关键初始化(比如设置 $this->config 或打开数据库连接),而子类又定义了自己的 __construct,却忘了调用 parent::__construct(),那父类的初始化逻辑就彻底跳过了——这不是警告,是静默失效。
典型场景:写了个 DatabaseConnection 父类负责连接初始化,子类 MySQLConnection 只加了 query 方法,但没调 parent::__construct(),结果 $this->link 始终为 null,后续所有查询都失败。
立即学习“PHP免费学习笔记(深入)”;
- 调用位置不限于开头,但建议放在子类构造函数第一行,避免使用未初始化的父类属性
- 如果父类构造函数需要参数,子类必须显式传入,例如
parent::__construct($host, $port) - PHP 不会自动推导或补全参数,漏传会导致
ArgumentCountError
参数默认值和类型声明能减少运行时判断
直接在 __construct 参数列表里设默认值或加类型,比在方法体内做 isset() 或 is_string() 判断更安全、更清晰。PHP 会在实例化那一刻就校验,而不是等执行到某一行才崩。
比如传入配置数组,不加约束容易导致后续 $this->config['timeout'] 报 Notice;加了 array $config = [] 就能提前兜底。
- 推荐用联合类型(PHP 8.0+)如
string|int|null $id = null,明确表达可选性 - 避免在构造函数里做耗时操作(如远程 API 调用、大文件读取),这会让对象创建不可控,也难测试
- 依赖注入场景下,优先接收接口类型(如
LoggerInterface $logger),而非具体类,利于解耦和 mock
构造函数里抛异常会中断实例化
__construct 中 throw Exception 或 InvalidArgumentException 是合法且推荐的做法——对象状态不合法时,就不该让它存在。PHP 会立即终止实例化流程,返回 null 不会发生,变量不会被赋值。
错误做法:构造失败后返回 false 或设 $this->valid = false,然后让调用方自己检查,这违背了“对象要么完整可用,要么不存在”的基本契约。
- 数据库连接失败、必填配置缺失、证书路径不存在等,都该在
__construct中抛异常 - 捕获异常要 catch 具体类型,别只写
catch (Exception $e),否则可能吞掉本该冒泡的致命错误 - 注意不要在构造函数里触发 autoload 失败(比如引用了未声明的类),这会导致
Fatal error: Class not found,无法被 try/catch 捕获



















