You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP 5.6.x中父类闭包实例化子类protected构造函数的行为是Bug吗?

结论:这是PHP 5.6.x的预期行为,PHP 7.x做了针对性行为修正

这是一个典型的PHP版本间闭包访问控制逻辑差异问题,具体细节拆解如下:

PHP 5.6.x的行为逻辑

在PHP 5.6及更早版本中,闭包的访问权限完全绑定到它被定义时的类上下文:

  • 当你在父类方法里定义一个闭包,这个闭包的"权限身份"就固定属于父类本身;
  • 当子类调用该父类方法时,闭包尝试实例化另一个拥有protected构造函数的子类——此时父类并没有权限访问这个子类的protected构造函数(protected成员仅允许类自身、它的直接/间接子类,以及通过该类实例访问,父类不属于目标子类的子类范畴);
  • 因此PHP 5.6会抛出权限错误,这是符合当时版本访问控制规则的预期结果。

PHP 7.x的行为调整

PHP 7.x对闭包的上下文绑定逻辑做了优化,让行为更符合开发者直觉:

  • 当闭包在类方法内部被调用时,它会继承调用时的类上下文权限;
  • 当子类调用父类方法触发闭包执行时,闭包的权限会切换到当前子类的上下文;
  • 由于子类和目标子类同属父类的派生类,在子类上下文下有权访问另一个子类的protected构造函数,因此实例化操作可以正常执行。

示例代码验证

class ParentClass {
    public function getCreatorClosure() {
        return function() {
            return new AnotherChild();
        };
    }
}

class CurrentChild extends ParentClass {
    public function createInstance() {
        $closure = $this->getCreatorClosure();
        return $closure();
    }
}

class AnotherChild extends ParentClass {
    protected function __construct() {}
}

// PHP 5.6执行报错:Call to protected AnotherChild::__construct() from context ''
// PHP 7.x及以上正常返回AnotherChild实例
$child = new CurrentChild();
$result = $child->createInstance();

这个调整是PHP官方为了解决PHP 5.x中闭包权限绑定过于僵化的问题,让闭包的权限逻辑更贴合实际开发场景而做出的改进。

内容的提问来源于stack exchange,提问作者dgaspar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:24:44