必须校验setter,否则等同于暴露public属性;校验应抛异常而非静默处理,需覆盖边界条件并与业务语义对齐,PHP 8.4 Accessors虽简化语法但不降低校验责任。

要加,而且必须加——不校验的 setter 和直接暴露 public 属性没本质区别。
为什么 setter 不校验等于放弃封装
封装的核心不是“把属性藏起来”,而是“控制怎么被改”。如果 setter 只是无条件赋值,那它只是个带括号的赋值语句,起不到任何保护作用。外部传入空字符串、负数、非法邮箱、超长文本,类内部状态就不可信了。
- 校验失败时应抛出异常(如
InvalidArgumentException),而不是静默忽略或强制转换 - 校验逻辑必须和业务语义对齐:比如
setEmail()用filter_var($email, FILTER_VALIDATE_EMAIL),不是只判非空 - 避免在
setter中做耗时操作(如远程 API 调用),否则调用方无法预期性能开销
PHP 8.4 Accessors 下校验写法更紧凑但约束没变
Accessors 的 set: 语法让校验逻辑内联在属性声明里,看起来更轻量,但责任一点没少。它不是“可以不校验”的借口,而是“校验更易组织”的工具。
public int $age { set: if ($value value = $value; }- 注意
$this->value是 PHP 自动维护的底层存储,别误写成$this->age - Accessors 不支持类型推导中的复杂校验(比如关联其他属性),此时仍需回退到传统
setter方法
哪些场景容易漏掉校验
最容易被忽略的不是“要不要校验”,而是“校验是否覆盖边界”。实际项目中高频踩坑点包括:
立即学习“PHP免费学习笔记(深入)”;
- 只校验非空,没校验长度(如用户名超过 32 字符导致数据库截断)
- 只校验数字类型,没校验范围(
int类型字段传入9999999999溢出) - 在
setter里修改传入值(如自动 trim 或转小写),却没在getter中保持行为一致,导致 == 判断失效 - DTO 类批量生成
setter后忘了补校验,尤其从 JSON 直接映射时
校验不是越严越好,而是要和领域规则对齐;但不校验,就等于把数据完整性交给了调用方——而你永远不知道谁会 new 一个对象然后传个 null 进来。



















