You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将PHP 8.1 Enum回退适配至PHP 8.0环境?

适配PHP 8.0的枚举替代方案

因为PHP 8.0不支持原生枚举,我们可以通过模拟枚举类实现相同功能,同时兼容你现有代码的调用方式和Laravel模型转换逻辑:

1. 替换原生Enum为模拟枚举类

创建一个类来模拟原生枚举的行为,同时实现Laravel的CastsAttributes接口以支持模型字段转换:

<?php

namespace App\Enums; // 根据你的项目命名空间调整

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class AssignmentState implements CastsAttributes
{
    // 定义对应状态的常量
    public const Draft = 'draft';
    public const Published = 'published';
    public const Graded = 'graded';

    private string $value;

    private function __construct(string $value)
    {
        $this->value = $value;
    }

    // 模拟原生枚举的->value获取方式
    public function value(): string
    {
        return $this->value;
    }

    // 静态方法模拟枚举实例化(如AssignmentState::Published())
    public static function Draft(): self
    {
        return new self(self::Draft);
    }

    public static function Published(): self
    {
        return new self(self::Published);
    }

    public static function Graded(): self
    {
        return new self(self::Graded);
    }

    // 从字符串值创建实例,用于模型转换
    public static function fromValue(string $value): self
    {
        if (!in_array($value, [self::Draft, self::Published, self::Graded])) {
            throw new \InvalidArgumentException("Invalid AssignmentState value: {$value}");
        }
        return new self($value);
    }

    // Laravel模型转换:从数据库读取时转换为枚举实例
    public function get($model, $key, $value, $attributes)
    {
        return $value ? self::fromValue($value) : null;
    }

    // Laravel模型转换:写入数据库时转换为字符串值
    public function set($model, $key, $value, $attributes)
    {
        if ($value instanceof self) {
            return $value->value();
        }

        // 直接传入字符串时验证合法性
        if (!in_array($value, [self::Draft, self::Published, self::Graded])) {
            throw new \InvalidArgumentException("Invalid AssignmentState value: {$value}");
        }
        return $value;
    }

    // 可选:实现__toString,方便直接输出值
    public function __toString(): string
    {
        return $this->value;
    }
}

2. 修改控制器中的调用逻辑

原来的AssignmentState::Published->value可以通过两种方式适配:

  • 方式1:直接使用常量(最简单,推荐)
$status = $request->has('status') ? $request->status : AssignmentState::Published;
  • 方式2:保持类似原生枚举的实例调用风格
$status = $request->has('status') ? $request->status : AssignmentState::Published()->value();

3. 模型中的$casts配置保持不变

原来的配置可以直接复用,因为模拟类实现了CastsAttributes接口,Laravel能自动处理字段转换:

protected $casts = [
    'status' => AssignmentState::class,
];

额外说明

  • 这个模拟类完全兼容原有业务逻辑:读取模型时$model->status会返回AssignmentState实例,写入时可直接传实例或合法的字符串值
  • 内置参数验证逻辑,避免非法状态值存入数据库
  • 判断状态时,既可以用常量对比($model->status === AssignmentState::Draft),也可以用实例的value方法对比($model->status->value() === AssignmentState::Draft)

内容的提问来源于stack exchange,提问作者Herman Ceaser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 13:33:31