
PHP封装不是“把代码包起来”这种模糊说法,而是指用 private、protected 明确限制属性和方法的可访问范围,并通过 public 的 getXXX() / setXXX() 方法控制外部如何读写数据——它本质是一套访问规则 + 一套交互约定。
为什么不能直接 public 属性就完事?
直接暴露 public $age 看似省事,但会立刻带来三类实际问题:
- 无法校验赋值合法性:比如
$user->age = -5或$user->age = "abc"不报错,后续逻辑可能崩溃 - 无法监听变更:年龄修改时想自动记录日志、触发事件、同步到缓存?没有入口点
- 无法兼容未来改动:今天存的是整数,明天要改成带单位的字符串(如
"25岁"),所有直接读$user->age的地方全得改
PHP 7.4+ 封装必须搭配类型声明
仅用 private 不够,PHP 7.4 起应强制加上属性类型,否则封装形同虚设:
class User {
private string $name; // ✅ 类型 + 访问控制
private int $age;
public function __construct(string $name, int $age) {
$this->name = $name;
$this->age = $age;
}
public function setAge(int $age): void {
if ($age 150) {
throw new InvalidArgumentException('年龄必须在 0~150 之间');
}
$this->age = $age;
}
}
如果没有 private string $name 这种声明,仅靠 setXXX() 方法,IDE 无法推断类型、静态分析失效、运行时也拦不住非法赋值(比如通过反射或数组强制写入)。
常见踩坑:getter/setter 写成摆设
很多代码看似封装了,实则只是“走形式”,这些写法等于没封:
-
public function getName() { return $this->name; }—— 没做任何校验或转换,和直接public $name几乎等价 -
public function setName($name) { $this->name = $name; }—— 不校验空值、长度、格式,不处理 trim 或大小写 - 对
private属性用__get()/__set()魔术方法统一代理 —— 失去类型提示、IDE 补全失效、调试困难
真正有效的封装,是每个 setXXX() 都有明确校验边界,每个 getXXX() 都能安全返回预期结构——它不是为了增加代码量,而是让“谁能在哪改什么”这件事,在代码层面可追踪、可约束、可演进。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











