Symfony项目中PHP if语句多OR逻辑状态校验的优雅实现咨询
Symfony 实体多状态校验的优化实现
原代码存在的问题
- 核心逻辑错误:原代码用
||串联排除条件的写法完全不符合需求。无论当前状态是什么,只要和三个排除值中的任意一个不相等,整个条件就会为真。比如状态是STATUS_FAILED时,因为它不等于STATUS_PROGRESS、不等于STATUS_DELETED,依然会错误进入分支执行setPreviousStatus操作。正确的基础逻辑应该把所有||替换为&&,即必须同时满足「不是三个排除状态中的任意一个」时,才执行赋值。- 可维护性差:重复多次调用
getStatus(),长串的条件判断增删改都需要修改整个判断表达式,后续调整排除状态时很容易漏改、写错。- 笔误问题:代码里写的
Entitiy是实体类名的拼写错误,实际使用时需要和类名保持一致,避免触发类常量不存在的运行报错。
基于数组函数的优雅实现
完全可以借助PHP内置的数组匹配函数替代多条件串联,这里不需要用到is_array()(该函数仅用于判断变量是否为数组类型),更适合的工具是in_array()。
兼容现有类常量的写法
- 首先在实体类内聚合所有需要排除的状态,统一维护:
// 实体类内部定义 const STATUS_FAILED = 'failed'; const STATUS_PROGRESS = 'progress'; const STATUS_DELETED = 'deleted'; // 聚合所有需要排除的状态,后续增删排除值只需要修改这个数组 const EXCLUDED_STATUSES = [ self::STATUS_FAILED, self::STATUS_PROGRESS, self::STATUS_DELETED, ];
- 判断逻辑简化为一次数组匹配:
// 第三个参数设为true开启严格类型比较,避免隐式类型转换带来的误判 if (!in_array($entity->getStatus(), Entity::EXCLUDED_STATUSES, true)) { $entity->setPreviousStatus($entity->getStatus()); }
这种写法的优势:
- 后续调整排除规则时,只需要修改
EXCLUDED_STATUSES数组的内容,不需要改动判断逻辑 - 去掉了冗余的重复
getStatus()调用,代码可读性更强 - 严格模式下的类型校验比手写多条件更安全,不会出现字符串、整型隐式转换导致的误匹配
适配PHP8.1+枚举的写法
如果项目使用PHP8.1以上版本,推荐用原生枚举替代类字符串常量,判断逻辑会更简洁:
// 定义实体状态枚举 enum EntityStatus: string { case Failed = 'failed'; case Progress = 'progress'; case Deleted = 'deleted'; case Other = 'other'; } // 直接用枚举自带的in方法做匹配 if (!$entity->getStatus()->in([ EntityStatus::Failed, EntityStatus::Progress, EntityStatus::Deleted, ])) { $entity->setPreviousStatus($entity->getStatus()->value); }
内容的提问来源于stack exchange,提问作者brighton
相关产品推荐
相关产品推荐

