Skip to content

trait 组合的 protected 方法,同类实例间调用被误判越权:报 cannot access protected method #67

Description

@xiaoyin199

trait 组合的 protected 方法,同类实例间调用被误判越权:报 cannot access protected method

已提交 issue:(待填)

环境

  • TypePHP Compiler (AOT) v0.6.8+(官方 master 10ecb944
  • libphp: PHP 8.4.24 NTS
  • OS: WSL2 Ubuntu x86_64

最小复现

<?php
// src/model.php
trait HasEvents {
    protected function fire(string $event): string {
        return 'fired:' . $event;
    }
}

class Base {
    use HasEvents;

    public function touchOther(): string {
        $other = new static();
        return $other->fire('x');  // 同类实例间 protected 调用,Zend 合法
    }
}
<?php
// src/entry.php
function main(int $argc, array $argv): void {
    echo (new Base())->touchOther(), "\n";
}
# typephp.yml
name: protected-scope
build-mode: bin
version: 0.1.0
output: build/protected-scope
build-dir: build/typephp
no-progress: true
sources:
  - ./src/entry.php
  - ./src/model.php

实际行为(AOT)

PHP Fatal error: Uncaught Error: Invalid callback Base::fire, cannot access protected method Base::fire()

预期行为(Zend)

输出 fired:x。PHP 的可见性是类作用域而非实例作用域:touchOther() 的执行作用域是 Base,对另一个 Base 实例调 protected 方法合法。

关键对照实验

fire() 直接声明在类里(不走 trait),同样的跨实例调用在 AOT 下正常

class Base {
    protected function fire(string $event): string { return 'fired:' . $event; }
    public function touchOther(): string {
        $other = new static();
        return $other->fire('x');   // ✅ AOT 下正常
    }
}

即问题特异于 trait 组合进来的方法:编译期把 trait 方法注入类时,方法的类作用域注册与直接声明不一致,运行时可见性检查(cannot access protected method)误判越权。

真实影响

命中 Hyperf 的 Model 链:Hyperf\Database\Model\Concerns\HasEvents(trait)定义的 protected fireModelEvent(),在 Model::newFromBuilder() 中以 $model->fireModelEvent('retrieved')(同类另一实例)调用——每次从数据库读取模型都会触发,登录、列表查询等全部崩溃。目前只能把 overlay 副本里的 fireModelEvent 放宽为 public 绕过。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions