PHP构造函数必须命名为__construct,大小写敏感且不可自定义;错误命名如__constructor将静默失效,导致初始化逻辑不执行。

PHP构造函数必须叫 __construct,不能写成 __constructor 或类名
这是最常踩的坑:手快打错函数名,或受其他语言影响误以为可以自定义名称。PHP 严格规定构造方法只能是 __construct(两个下划线开头),且大小写敏感。写成 __constructor、Construct 或 myConstructor 都不会被自动调用,也不会报错,只会静默失效——对象创建后初始化逻辑直接跳过。
常见错误现象:
• 类里写了初始化代码但没执行
• $obj = new MyClass(); 后属性仍是 null 或默认值
• 调试时发现 var_dump($obj) 显示预期字段未赋值
- 类中只能有一个
__construct方法;多个会报Fatal error: Cannot redeclare MyClass::__construct() - 如果父类有
__construct,子类重写时需显式调用parent::__construct(...),否则父类逻辑不执行 - PHP 8.0+ 支持构造函数属性提升(property promotion),可把参数直接声明为属性:
public function __construct(public string $name, private int $id) { },省去手动赋值
参数类型和默认值要和实际传入严格匹配
构造函数本质是普通方法,参数校验规则完全一致。传参类型不符、缺失必填参数、或传了 null 给非空类型,都会触发错误——但具体表现取决于 PHP 版本和严格模式设置。
使用场景:
• 创建数据库连接对象时传入 $host、$port
• 实例化配置类时传入 $configPath 并尝试读取文件
立即学习“PHP免费学习笔记(深入)”;
- 启用
declare(strict_types=1);后,类型不匹配直接抛TypeError;否则可能静默转换(如"123"转成int 123) - 带默认值的参数必须放在参数列表末尾,否则会报
Parse error: default argument follows non-default argument - 避免在构造函数里做耗时操作(如远程请求、大文件读取),否则 new 一个对象就卡住;这类逻辑建议拆到单独的
init()或工厂方法中
示例:
class Logger {
public function __construct(private string $path, private bool $enabled = true) {
// $path 必须是 string,$enabled 可选,默认 true
if (!is_writable($path)) {
throw new InvalidArgumentException("Log path not writable: {$path}");
}
}
}
构造函数里不要依赖尚未初始化的静态属性或全局状态
PHP 类加载和静态属性初始化顺序容易被忽略。如果在 __construct 中读取 self::$config,而该静态属性在类定义后才被赋值(比如在另一个文件里写 MyClass::$config = [...];),那构造时拿到的就是 null 或旧值。
常见错误现象:
• 单元测试里反复 new 对象,结果有时正常有时配置为空
• CLI 和 Web 环境行为不一致(因加载顺序不同)
- 静态属性应在类定义内部直接初始化:
private static array $config = ['debug' => false]; - 若必须外部注入配置,改用依赖注入(DI)方式,把配置作为参数传进构造函数,而不是靠“先设静态变量再 new”这种脆弱约定
- 避免在构造函数中调用
getenv()、$_SERVER等全局变量——它们可能在 CLI 下为空,或被中间件修改
PHP 8.1+ 析构函数 __destruct 不保证一定执行,别放关键清理逻辑
虽然这不是构造函数本身,但新手常把两者绑在一起理解。PHP 的垃圾回收不是实时的,__destruct 的触发时机不确定:脚本结束前、内存不足时、引用计数归零时都可能,也可能压根不触发(比如进程被 kill -9)。
所以别指望靠 __destruct 关闭数据库连接、释放锁、写日志——这些必须由业务层主动控制。
- 构造函数里打开的资源(如
fopen()返回的句柄),应在业务方法中配对关闭,或用try/finally保证 - 如果真要用
__destruct,只处理无副作用的清理(如unset($this->tempData)),且加if (is_resource($this->handle)) { fclose($this->handle); }防重复关闭 - CLI 脚本中长生命周期对象(如 Worker)更要警惕:
__destruct可能等到整个进程退出才跑,期间资源一直占用









