PHP 8.0 中 static 作返回类型(: static)与 LSB 调用(static::)语义隔离:前者声明返回当前调用类实例,需配合 return $this 或 new static();后者是运行时动态解析类作用域的调用语法,二者不可互换。

PHP 8.0 不支持 static 作为方法调用语法的一部分 —— 它只能用作返回类型声明,不能像 self::method() 那样被“调用”。
为什么你不能写 static::someMethod() 来触发静态返回类型行为
这是最常见的误解来源:static 在 PHP 中是后期静态绑定(LSB)关键字,用于 static:: 调用类成员,但它和 : static 返回类型声明完全无关。两者同名但语义隔离:
-
static::是运行时解析的类作用域访问方式,等价于get_called_class(),用于调用静态方法或读取静态属性; -
: static是 PHP 8.0+ 引入的返回类型语法,仅出现在函数签名末尾,告诉类型系统“这个方法返回当前实际调用类的实例”; - 你无法“调用”返回类型——它不执行任何逻辑,只参与类型推导与静态分析。
: static 必须配合 return $this 或 new static() 才有意义
光写 public function withName(string $n): static 没用,必须在方法体内返回兼容值,否则会报错或破坏链式调用:
- 对于可变对象(如构建器、DTO),常用
return clone $this+ 属性赋值; - 对于不可变对象或工厂方法,应写
return new static($args); - 若返回
$this但方法体里做了unset($this->prop)或重置了关键状态,类型虽对,行为已错; - 注意:如果父类方法声明了
: static,子类覆盖时也必须保持相同返回类型,否则 PHP 会报Declaration must be compatible错误。
和 : self 混用会导致类型推导断裂
这是 IDE 补全失效、PHPStan 报告 Call to an undefined method 的高频原因:
立即学习“PHP免费学习笔记(深入)”;
- 假设基类
Builder中有public function where(): self,而子类PostBuilder extends Builder覆盖该方法并改用: static—— 类型系统无法统一推导链式路径; - 所有链式方法必须统一使用
: self(适合封闭继承体系)或全部用: static(适合开放扩展,如 Laravel 的 Eloquent Builder); - PHPStorm 和 Psalm 默认按第一个方法的返回类型向下推导,中间混入不同返回类型就会中断补全;
- 别指望加个
@return static注释能绕过 —— PHP 8.0+ 的原生: static是硬约束,注释只是软提示。
实际能“调用”的只有 static::,但它不决定返回类型
如果你看到类似 static::make() 这样的写法,那只是利用 LSB 实现类名动态解析,和返回类型无关:
-
static::make()等价于get_called_class()::make(),它确保调用的是子类的make静态方法; - 该方法的返回类型仍需单独声明为
: static,否则即使调用正确,IDE 也不知道返回什么; - 例如
class User { public static function create(): static { return new static(); } }—— 这里static::create()是调用方式,: static是返回承诺; - 漏掉
: static声明,PHP 不报错,但User::create()->getName()在 PHPStan 中会被视为 “可能调用未定义方法”。
真正容易被忽略的是:返回类型声明本身不改变运行时对象身份,它只约束返回值是否满足“是当前调用类的实例”这一条件。哪怕你写了 : static,如果方法里返回了 new ParentClass(),PHP 会在运行时直接抛 TypeError —— 不是警告,是致命错误。



















