应使用private属性配合getter/setter方法而非直接暴露public属性。这能确保数据一致性、支持校验转换逻辑、发挥PHP类型声明作用、降低重构成本,并通过行为抽象提升业务语义表达与可维护性。

直接暴露属性会破坏数据一致性
把 $email、$age 这类字段设为 public,外部代码就能绕过任何校验随意赋值:$user->email = "not-an-email";、$user->age = -5;。这类赋值不会触发任何逻辑,对象瞬间进入非法状态,而错误往往延迟到后续调用才暴露,排查成本高。
getter/setter 是可控的数据入口
用 private 属性 + public 方法组合,才能在关键节点插入约束和转换逻辑:
-
setName()可以 trim 空格、过滤 XSS 标签、强制首字母大写 -
setEmail()能调用filter_var($email, FILTER_VALIDATE_EMAIL)即时拦截非法值 -
getCreatedAt()可统一返回格式化字符串,而不是暴露原始DateTime对象让调用方自己处理时区
类型声明 + private 属性才是 PHP 7.4+ 的安全基线
PHP 7.4 开始支持属性类型声明,但只有配合 private 才真正起作用:
class User {
private string $name;
private int $age;
public function setName(string $name): void {
$this->name = trim($name); // 仍需清理
}
public function setAge(int $age): void {
if ($age 150) {
throw new InvalidArgumentException('Invalid age');
}
$this->age = $age;
}
}
如果把 $name 改成 public string $name;,类型检查只在赋值时生效,但无法阻止 $user->name = ""; 或 $user->name = str_repeat("x", 10000); 这类语义错误。
行为暴露更利于未来重构
当业务变化需要把 $status 从字符串改为枚举类、或把 $score 计算逻辑从简单加法改为调用远程 API,只要接口方法名和参数不变,所有调用方完全无感。而直接读写属性意味着所有外部代码都和内部字段名、类型、存储方式强耦合,改一处,全项目报错。
真正难的不是写 getXXX(),而是想清楚这个“行为”该承担什么职责——比如 canAccessPremiumContent() 比 isSubscribed + hasValidPayment + isNotBanned 的组合判断更贴近业务语义,也更容易测试和复用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











