PHP类混乱主因是属性暴露、方法职责不清、访问控制缺失;须以private/protected封装数据,用具校验的setter替代public属性,禁用无条件__set,构造函数仅赋值不执行逻辑,依赖通过参数注入。

直接说结论:乱的PHP类,90%的问题出在属性暴露、方法职责不清、访问控制缺失这三点上。封装不是加个private就完事,而是用访问修饰符+方法边界+命名意图三者协同收口。
为什么public属性一写就乱
把$name、$email全设成public,等于把数据库表字段直接拖到对象外面裸奔。外部代码可以随意赋值、跳过校验、绕过业务逻辑——比如$user->email = 'xxx';之后,没人知道这个邮箱有没有被过滤或去重。
- 所有本该受控的数据(如状态、ID、时间戳)必须声明为
private或protected -
public只留给真正需要外部自由读写的配置项(比如$debugMode这种开关) - 一旦发现
public属性被频繁赋值,立刻检查是否该抽成setEmail()这类带校验的方法
__get和__set不是万能补丁
有人觉得“反正都乱了,不如用魔术方法兜底”,结果写出一堆无条件透传的__set,跟public没区别。这两个方法只在两种场景下合理:
- 需要动态代理访问(比如统一处理未定义属性的日志或降级)
- 配合
private属性做懒加载或计算属性(例如$user->fullName由firstName和lastName拼接而来) - 其他情况——尤其是CRUD类模型——老老实实写
getName()/setName(),让调用方明确知道这是有副作用的操作
构造函数里别塞逻辑,先封住入口
常见烂代码:__construct()里直接查数据库、发HTTP请求、写日志。这导致对象创建失败风险高、无法单元测试、依赖不可控。
立即学习“PHP免费学习笔记(深入)”;
- 构造函数只做两件事:接收参数、赋值给
private属性 - 把初始化逻辑拆进单独的
init()或loadFromDb()方法,调用方按需触发 - 如果类必须依赖外部服务(如
UserRepository),用构造函数参数注入,而不是在内部new一个
最易被忽略的一点:封装不是为了“防同事”,而是为了降低后续修改成本。当你改一个private属性的类型时,IDE能立刻标出所有要同步更新的getter/setter;而满屏public属性,你得靠grep人肉翻——这时候你就知道,当初少打的那几个private关键字,正在以小时为单位吃掉你的调试时间。



















