PHP类属性访问修饰符规范的核心是运行时强制执行的访问控制机制,public允许任意访问,protected限于类及子类,private严格限定于声明类本身,且三者序列化格式不同。

PHP类属性访问修饰符规范的核心是明确限定属性的可访问范围,确保封装性与安全性。它不是语法糖,而是运行时强制执行的访问控制机制——越界访问会直接触发 Fatal error,而非警告或静默忽略。
public:开放访问,无边界限制
public 属性可在任何上下文中读写:类内部、子类中、以及通过对象实例从外部直接调用。
- 定义时不加修饰符默认为 public(但显式声明更清晰、更符合现代编码规范)
- 适合暴露稳定接口,如 DTO 字段、配置项、API 返回数据结构
- 注意:滥用 public 容易导致外部代码强耦合内部实现,修改时风险高
protected:继承友好,外部隔离
protected 属性仅允许在定义它的类及其子类中访问,类外部无法通过 $obj->prop 方式读写。
- 子类可通过
$this->prop直接使用,无需 getter/setter - 典型用途:模板方法中的钩子属性、缓存字段、需被子类复用但不对外暴露的状态
- 不能被同级类或无关对象访问,哪怕它们属于同一命名空间
private:严格私有,作用域锁定到单个类
private 属性只能在声明它的那个类内部访问,子类也不得直接访问——即使重名、继承关系再深,也会报错。
立即学习“PHP免费学习笔记(深入)”;
- PHP 将 private 视为“类体级私密”,不参与继承链可见性传递
- 若子类需要类似能力,应改用 protected;或由父类提供 public/protected 的受控访问方法
-
__get/__set魔术方法对 private 属性无效,它们只响应不可见的 public 属性或不存在的属性
序列化时的编码差异必须留意
不同修饰符会影响序列化字符串的格式,尤其在反序列化漏洞利用或跨系统数据交换中极易出错:
- public 属性名原样出现:
s:8:"username" - protected 属性名前缀
%00*%00:s:12:"%00*%00username" - private 属性名前缀
%00类名%00,且类名需 URL 编码两次:s:15:"%2500User%2500pwd" - 手动构造或篡改序列化字符串时,漏掉前缀或编码错误会导致反序列化失败或属性丢失



















