How to persist enum with Symfony Doctrine (entity field type:"enum")

Yes doctrine does not support php Enum from version 8.1 but you can create your own Doctrine type. Defining a custom Doctrine type

In your case it should be something link this:

<?php

namespace App\DBAL;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;
use App\Enum\GradeEnum;
use InvalidArgumentException;
use JetBrains\PhpStorm\Pure;

class GradeType extends Type
{
    protected string $name;
    protected array $values = [
        GradeEnum::A5plus,
        GradeEnum::A5,
        GradeEnum::A4,
        GradeEnum::A3,
        GradeEnum::A2,
        GradeEnum::A1,
        GradeEnum::B2,
        GradeEnum::B1,
        GradeEnum::C2,
        GradeEnum::C1,
        GradeEnum::D2,
        GradeEnum::D1,
    ];

    const GRADE = 'grade';

    public function getName(): string
    {
        return self::GRADE;
    }

    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
    {
        $values = array_map(function ($val) {
            /** @var GradeEnum $val */
            return "'{$val->name}'";
        }, $this->values);

        return 'ENUM(' . implode(', ', $values) . ')';
    }

    #[Pure]
    public function convertToPHPValue($value, AbstractPlatform $platform): ?GradeEnum
    {
        if (null === $value) {
            return null;
        }
        return GradeEnum::getGradeFromString($value);
    }

    public function convertToDatabaseValue($value, AbstractPlatform $platform)
    {
        /** @var GradeEnum $value */
        if ($value !== null) {
            if (!in_array($value, $this->values)) {
                throw new InvalidArgumentException("Invalid '" . $this->name . "' value.");
            } else {
                return $value->name;
            }
        }

        return null;
    }

    public function canRequireSQLConversion(): bool
    {
        return true;
    }

    public function requiresSQLCommentHint(AbstractPlatform $platform): bool
    {
        return true;
    }
}
<?php

namespace App\Enum;

enum GradeEnum: int
{
    case A5plus = 0;
    case A5 = 1;
    case A4 = 2;
    case A3 = 3;
    case A2 = 4;
    case A1 = 5;
    case B2 = 6;
    case B1 = 7;
    case C2 = 8;
    case C1 = 9;
    case D2 = 10;
    case D1 = 11;

    public static function getGradeFromString(string $grade): GradeEnum {
        return match ($grade) {
            self::A5plus->name => self::A5plus,
            self::A5->name => self::A5,
            self::A4->name => self::A4,
            self::A3->name => self::A3,
            self::A2->name => self::A2,
            self::A1->name => self::A1,
            self::B1->name => self::B1,
            self::B2->name => self::B2,
            self::C1->name => self::C1,
            self::C2->name => self::C2,
            self::D1->name => self::D1,
            self::D2->name => self::D2,
        };
    }
}

Do not forget to add your type into your doctrine.yaml

doctrine:
    dbal:
        types:
            grade: App\DBAL\GradeType
        mapping_types:
            enum: string
            grade: grade

Have a good day !


Starting with version 2.11, the ORM supports php 8 enums

enum Suit: string {
    case Hearts = 'H';
    case Diamonds = 'D';
    case Clubs = 'C';
    case Spades = 'S';
}

#[Entity]
class Card
{
    /** ... */

    #[Column(type: 'string', enumType: Suit::class)]
    public $suit;
} 

You can read more about this in the offical blog post. Official docs should follow soon.