::是作用域解析操作符,用于指定从哪个类取成员;->是实例操作符,仅作用于对象。静态方法不可用->调用,因会强制绑定不存在的$this;::可调非静态方法但危险,php 8.2+已弃用。

PHP里::和->到底在区分什么
因为::不是“调用静态方法的符号”,而是“作用域解析操作符”(Scope Resolution Operator),它解决的是“从哪个类/作用域里取东西”的问题。而->是对象实例的操作符,只认$obj这种有内存地址的东西。
所以根本不是“静态方法必须用::”,而是:你没实例化对象、没$this上下文时,只能靠::显式指定类作用域——否则PHP不知道你要找的是Foo::bar()还是Bar::bar(),哪怕它们同名。
-
Foo::staticMethod():明确说“我要调Foo这个类定义里的staticMethod,不看实例、不走继承链上的重写” -
$obj->instanceMethod():依赖$obj的实际类型,会触发动态绑定(比如子类重写了就调子类的) - 连
self::、static::、parent::也都是::的变体,本质仍是作用域定位,不是“静态专属”
为什么不能用->调静态方法
PHP会报Fatal error: Uncaught Error: Using $this when not in object context——哪怕方法声明为static,->语法本身就会强制绑定$this,而静态调用时根本没有$this。
更隐蔽的问题是:如果某个静态方法内部用了$this,用->调用它不会立刻报错(PHP 8.0+才严格拦截),但运行时一访问$this->xxx就崩。这不是语法错误,是逻辑错位。
- 静态方法里写
$this->prop→ 直接Fatal - 静态方法里只用
self::$prop→ 安全,但用->调仍属误用,语义混乱 - PHP 8.1+开始对
->调静态方法发出Deprecated警告,未来版本会禁用
::也能调非静态方法?危险但合法
可以,但极其危险:Foo::instanceMethod()能跑通,前提是该方法没用$this。一旦用了,就触发上面那个Fatal错误。
这种写法绕过了对象生命周期检查,等于把实例方法当函数用——破坏封装、跳过构造逻辑、无法依赖$this->__construct()初始化的状态。
- 常见于遗留代码中“偷懒不实例化”,比如
Config::get('db.host')但get()其实是public function get()而非public static function get() - PHP 8.2+已将此类调用标记为
Deprecated,并会在方法含$this引用时直接报错 - 工具如PHPStan或Psalm默认告警,CI里容易被卡住
继承场景下self:: vs static::的坑
这是::最易混淆的点:两者都用双冒号,但绑定时机不同。写错会导致静态属性或方法调用“卡在父类”,而不是按实际调用者类型走。
-
self::METHOD()→ 编译期绑定,永远指向定义该代码的类(哪怕子类调用) -
static::METHOD()→ 运行时绑定(Late Static Binding),指向实际调用的类(类似$this的动态性) - 例如
Child::foo()里写self::bar(),调的是Parent::bar();写static::bar()才调Child::bar()
绝大多数需要多态行为的静态场景(比如工厂模式、单例子类化),必须用static::,否则继承失效。这个细节没有报错,但结果不对,调试起来特别慢。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











