Eloquent 是否支持数组类型的 Enum 枚举类型转换?
Laravel 数组枚举转换实现方案
核心结论
Laravel 原生提供的 Enum Cast 仅支持单个枚举值的转换,不直接支持数组类型值的批量枚举转换,你可以通过以下几种原生方案实现同类需求。
替代实现方案
方案1:自定义 Cast 类(最推荐)
Laravel 支持自定义转换类,你可以自行实现数组枚举的转换逻辑,复用性和规范性最高:
- 新建自定义转换类
app/Casts/EnumArray.php:
<?php namespace App\Casts; use Illuminate\Contracts\Database\Eloquent\CastsAttributes; class EnumArray implements CastsAttributes { public function __construct(protected string $enumClass) {} public function get($model, string $key, $value, array $attributes) { if (is_null($value)) { return []; } $values = json_decode($value, true); return array_map(fn($val) => $this->enumClass::from($val), $values); } public function set($model, string $key, $value, array $attributes) { if (is_null($value)) { return null; } return json_encode(array_map(fn($enum) => $enum->value, $value)); } }
提示:如果需要兼容数据库可能存在的无效枚举值,可以将代码中的
from方法替换为tryFrom,无效值会返回null,你可以根据业务需要自行过滤或抛出异常。
- 在模型的
$casts属性中声明使用:
use App\Casts\EnumArray; use App\Enums\ServerStatus; protected $casts = [ // 原单个枚举转换 'status' => ServerStatus::class, // 数组枚举转换,冒号后传入目标枚举类 'allowed_statuses' => EnumArray::class . ':' . ServerStatus::class, ];
配置完成后,allowed_statuses 属性会自动在「数据库存储的JSON字符串」和「枚举实例数组」之间互转,使用方式如下:
// 读取时直接得到枚举实例数组 foreach ($server->allowed_statuses as $status) { if ($status === ServerStatus::ready) { // 业务逻辑 } } // 赋值时直接传枚举实例数组即可自动存储 $server->allowed_statuses = [ ServerStatus::provisioned, ServerStatus::ready, ServerStatus::archived ]; $server->save();
方案2:访问器+修改器(兼容低版本Laravel)
如果你不想额外新建Cast类,也可以直接在模型中定义访问器和修改器实现转换,无需额外依赖:
use App\Enums\ServerStatus; // 访问器:读取时转换为枚举数组 public function getAllowedStatusesAttribute($value) { if (is_null($value)) return []; return array_map(fn($val) => ServerStatus::from($val), json_decode($value, true)); } // 修改器:写入时转换为JSON字符串存储 public function setAllowedStatusesAttribute($value) { $this->attributes['allowed_statuses'] = json_encode( array_map(fn($enum) => $enum->value, $value) ); }
注意事项
- 存储枚举数组的数据库字段需要设置为
json或者text类型,支持存储JSON格式字符串 - 如果枚举是纯数字的backed枚举,也可以根据业务需要存储为逗号分隔的字符串,只需修改自定义Cast或者访问器/修改器的转换逻辑即可
内容的提问来源于stack exchange,提问作者k0pernikus
相关产品推荐
相关产品推荐

