Laravel 用 Enum 与 Casts 把状态字段变成类型安全枚举,告别魔法字符串
test12026-10-093 次阅读
魔法字符串的代价
订单状态、审核结果这类字段,常见写法是表里存字符串,业务里到处比较 $order->status === 'pending'。拼写错一个字母就悄悄走了错误分支,IDE 也帮不上忙。PHP 8.1 的枚举配合 Laravel 的 Casts 能把字段变成真正的类型,赋值和判断都受编译期与运行期双重约束。
定义 backed enum
用 string backed enum 把合法取值固定下来,每个 case 对应数据库里存的值。
namespace App\Enums;
enum OrderStatus: string
{
case Pending = 'pending';
case Paid = 'paid';
case Shipped = 'shipped';
case Done = 'done';
case Cancelled = 'cancelled';
}
用 Cast 绑定模型字段
在模型里用 $casts 把 status 字段映射到枚举,读写时 Laravel 自动转换,拿到的是 OrderStatus 实例而非裸字符串。
namespace App\Models;
use App\Enums\OrderStatus;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
protected $casts = [
'status' => OrderStatus::class,
];
}
类型安全地赋值与判断
赋值只能传枚举 case,比较用身份运算符,拼错 case 直接编译报错;还能给枚举加方法封装状态流转规则。
$order = Order::find(1);
// 赋值:只能是枚举,传字符串会抛异常
$order->status = OrderStatus::Paid;
$order->save();
// 判断:用身份比较,安全清晰
if ($order->status === OrderStatus::Paid) {
// 已支付分支
}
// 查询:直接传枚举,底层自动转成存储值
Order::where('status', OrderStatus::Shipped)->count();
实践建议
- 枚举适合"有限且稳定"的取值集;状态还会频繁新增时,谨慎评估是否值得上枚举。
- 给枚举加方法能收口流转逻辑,例如 canTransitionTo(OrderStatus $next) 统一把关。
- 数据库迁移里把字段设成与 enum 对应的值类型(如 varchar 或 tinyint),避免存储歧义。
- 旧项目改造可平滑过渡:先加 enum 与 cast,再逐步替换散落的字符串比较。
T
test1
文章作者
魔法字符串的代价 订单状态、审核结果这类字段,常见写法是表里存字符串,业务里到处比较 $order->status =...
- 分类
- 技术
- 发布时间
- 2026-10-09
- 字数
- 约 1240 字
- 阅读
- 3 次
