PHP中::只能访问static声明的成员,误用于实例属性或方法会触发Fatal error;非静态成员必须通过对象实例调用;self编译时绑定,static运行时绑定支持后期静态绑定。
:: 访问实例属性或方法PHP 中 :: 是作用域解析操作符,用于访问类的静态成员、常量或父类中被覆盖的方法。但它**不能**用来访问未声明为 static 的属性或方法——否则会触发 Fatal error: Uncaught Error: Access to undeclared static property 或 Call to undefined method。
常见错误写法:
class User {
public $name = 'guest';
public function greet() { return "Hello"; }
}
echo U
ser::$name; // ❌ Fatal error
User::greet(); // ❌ Fatal error
正确做法是:只对明确标记为 static 的成员使用 :::
class User {
public static $role = 'user';
public static function getRole() { return self::$role; }
}
echo User::$role; // ✅
echo User::getRole(); // ✅
$u = new User(); echo $u->name; $u->greet();
$this 和 self/static 时尤其容易出错——$this 在静态上下文中不可用,会报 Fatal error: Using $this when not in object context
self、static 和 parent 在静态调用中的区别
三者都用于静态上下文中的类内引用,但绑定时机和行为不同:
self:编译时绑定,始终指向定义该代码的类(不支持后期静态绑定)static:运行时绑定(LSB),指向实际调用的类(支持继承重写)parent:指向当前类的父类,仅用于显式调用父类静态成员示例对比:
class A {
protected static $msg = 'A';
public static function say() { return self::$msg; } // 绑定 A
public static function tell() { return static::$msg; } // 绑定调用者
}
class B extends A {
protected static $msg = 'B';
}
echo A::say(); // A(self 固定在 A)
echo B::say(); // A(self 仍在 A)
echo A::tell(); // A(static 指向 A)
echo B::tell(); // B(static 指向 B)
多数情况下推荐用 static 替代 self,除非你明确需要“锁定到当前类”;滥用 self 是静态方法无法被子类正确覆盖的常见原因。
看似安全的写法,可能因调用方式意外进入静态上下文:
self::doSomething() 是合法的,但如果该方法本身不是 static,而你又在静态方法中调用了它,就会崩__callStatic)未正确定义时,User::nonExistMethod() 会直接报错而非走兜底逻辑User::find(1))本质是工厂模式,但若自定义了 __callStatic 却没处理所有情况,就容易漏掉链式调用(如 User::where(...)->first())检查要点:
static 声明__callStatic,并覆盖了预期的动态静态方法名$this 或调用 $this->xxx ——这属于硬性语法错误没有语法能阻止开发者写错,但清晰的命名和注释能大幅减少误判:
createFromArray()、getDefaultConfig(),避免和实例方法(如 save()、validate())混淆@static,并说明是否支持 LSB(即是否应使用 static::)self:: 对非静态成员的引用,或未声明 static 却被静态调用的情况最常被忽略的一点:const 默认就是静态的,但 const 只能在类顶层定义,不能在方法内;而 define() 定义的是全局常量,跟类作用域无关——这两者混用也会导致 :: 查找失败。
# php
# phpstorm
# laravel
# access
# 工具
# 区别
# 作用域
# red
# echo
# Static
# Object
# 常量
# define
# 父类
# 子类
# 构造函数
# Error
# const
# 类作用域
# 继承
# using
# Property
# undefined
# 对象
# this
# ide
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
网络优化76771 】
【
技术知识130152 】
【
IDC云计算60162 】
【
营销推广131313 】
【
AI优化88182 】
【
百度推广37138 】
【
网站推荐60173 】
【
精选阅读31334 】
相关推荐:
Win10如何备份驱动程序_Win10驱动备份步骤【攻略】
Win11触摸板没反应怎么办_开启Win11笔记本触摸板手势教程【步骤】
c++怎么实现大文件的分块读写_c++ 文件指针seekp与seekg偏移控制【方法】
Python网络日志追踪_请求定位解析【教程】
如何提升Golang程序I/O性能_Golang I/O密集型程序优化示例
如何用正则与预处理高效拦截带干扰符的恶意域名
php485在php5.6下能用吗_php485旧版本兼容性问题说明【详解】
php8.4如何配置ssl证书_php8.4https访问配置指南【教程】
c++如何实现一个高性能的环形队列(Ring Buffer)_c++无锁实现方法【并发】
PhpStorm怎么调试PHP代码_PhpStorm断点设置与调试启动步骤【指南】
c++怎么实现高并发下的无锁队列_c++ std::atomic原子变量与CAS操作【详解】
Win11应用商店下载慢怎么办 Win11更改DNS提速下载【修复】
Windows如何拦截2345弹窗广告_Windows拦截2345弹窗方法【步骤】
c++如何用AFL++进行模糊测试 c++ Fuzzing入门【安全】
微信企业付款回调PHP怎么接收_处理企业付款异步通知数据教程【教程】
如何在Mac上搭建Golang开发环境_使用Homebrew安装和管理Go版本
如何使用Golang实现跨域请求支持_Golang CORS配置与处理方法
Win11怎么设置环境变量_Win11配置Path路径变量【详解】
php串口通信波特率怎么选_根据硬件手册设置正确波特率【方法】
如何使用Golang实现多重错误处理_Golangerror组合与判断方法
如何在 Go 中高效缓存与分发网络视频流
Mac如何修改Hosts文件?(本地开发与屏蔽网站)
Go 语言标准库为何不提供泛型 Contains 方法?
Python函数缓存机制_lru_cache解析【指导】
Win11怎么设置任务栏图标大小_Windows11注册表TaskbarSi修改
Win11怎么开启远程桌面连接_Windows11系统属性远程设置
Win10怎么创建桌面快捷方式 Win10为应用创建快捷方式【步骤】
如何使用Golang实现路由参数绑定_使用Mux和Request解析路径变量
php中self::能调用子类重写的方法吗_静态绑定与重写关系【介绍】
c++ nullptr与NULL区别_c++11空指针规范
php内存溢出怎么排查_php内存限制调试与优化方法【说明】
php485函数执行慢怎么优化_php485性能提升小技巧【技巧】
如何在Golang中修改数组元素_通过指针实现原地更新
Windows10系统怎么查看显卡型号_Win10 dxdiag显示选项卡
Mac怎么设置鼠标滚动速度_Mac鼠标设置详细参数
Win11截图快捷键是什么_Win11自带截图工具使用技巧【汇总】
Win11右键反应慢怎么办 Win11优化右键菜单加载速度【技巧】
Win10闹钟铃声怎么自定义 Win10闹钟自定义铃声教程【方法】
c# await 一个已经完成的Task会发生什么
如何在 Go 应用中实现自动错误恢复与进程重启机制
Win11时间格式怎么改成12小时制 Win11时间格式切换教程【步骤】
php485支持哪些操作系统_php485跨系统支持情况介绍【解答】
Django密码修改后会话失效的解决方案
Win10如何卸载微软拼音输入法 Win10只保留一个输入法【教程】
如何在 Go 中创建包含映射(map)的切片(slice)结构
c++的mutex和lock_guard如何使用 互斥锁保护共享资源【多线程】
Win11文件扩展名怎么显示 Win11查看文件后缀名设置【步骤】
Windows10电脑怎么设置虚拟光驱_Win10右键装载ISO镜像文件
Win11文件夹预览图不显示怎么办_Win11缩略图缓存重建修复【教程】
Win11怎么开启远程桌面_Win11系统远程桌面启用开关
2026-01-04
致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。