Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What do you use instead of ENUM in doctrine2?

What do you use instead of ENUM in Doctrine2? smallint? I thought of using varchar, or explicitly define char, but this may not be very effective when it comes to indexes, or am I wrong?

like image 521
DavidW Avatar asked Jan 05 '12 22:01

DavidW


3 Answers

I usually work with integers mapped to class constants, like

class MyEntity {
    const STATUS_INACTIVE = 0;
    const STATUS_ACTIVE = 1;
    const STATUS_REFUSE = 2;

    protected $status = self::STATUS_ACTIVE;
}

That works quite fine and makes it even easier to work with what you would call ENUMS in an IDE.

You can also use an enumerable type as described by the documentation, but that means you will have to define one custom type per enum column. That's a lot of work with no real benefit.

You may also want to know why you shouldn't really use enums.

like image 170
Ocramius Avatar answered Nov 03 '22 06:11

Ocramius


Postgres, Symfony, ORM, Doctrine...

  1. Postgres: Define new type enum (pgAdmin)

    CREATE TYPE new_enum AS ENUM ('sad', 'ok', 'happy');
    
  2. In Entity

    @ORM\Column(name="name", type="string", columnDefinition="new_enum", 
    nullable=true)
    
  3. In config.yml

    mapping_types:
        new_enum: string
    

     

    # Doctrine Configuration
    doctrine:
        dbal:
            driver:   "%database_driver%"
            host:     "%database_host%"
            port:     "%database_port%"
            dbname:   "%database_name%"
            user:     "%database_user%"
            password: "%database_password%"
            charset:  UTF8
            mapping_types:
                new_enum: string # <=======
    
like image 44
websky Avatar answered Nov 03 '22 06:11

websky


If you want MySQL ENUMs using MySQL and Symfony, you can now use an easy way for that without any dependencies

use a base class for all enums:

<?php

namespace App\Enum;

use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;

abstract class EnumType extends Type
{
    protected $name;
    protected $values = [];

    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
    {
        $values = array_map(function($val) { return "'".$val."'"; }, $this->values);

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

    public function convertToPHPValue($value, AbstractPlatform $platform)
    {
        return $value;
    }

    public function convertToDatabaseValue($value, AbstractPlatform $platform)
    {
        if (!in_array($value, $this->values)) {
            throw new \InvalidArgumentException("Invalid '".$this->name."' value.");
        }
        return $value;
    }

    public function getName()
    {
        return $this->name;
    }

    public function requiresSQLCommentHint(AbstractPlatform $platform)
    {
        return true;
    }
}

extend it for your special case:

namespace App\Enum;

 class UploadFileStatusType extends EnumType
{
     const OPEN = 'open';
     const DONE = 'done';
     const ERROR = 'error';

     protected $name = self::class;

     protected $values = [
         self::OPEN => self::OPEN ,
         self::DONE => self::DONE,
         self::ERROR => self::ERROR,
     ];

}

add it to your dcotrine.yml config file:

doctrine:
    dbal:
        types:
            UploadFileStatusType: App\Enum\UploadFileStatusType

use it in your entity file as doctrine column doc type:

class MyEntity
{
    /**
     * @var string
     *
     * @ORM\Column(type="UploadFileStatusType")
     */
    protected $status;
}

And you will end up with a clean MySQL ENUM type for column status:

enum('open', 'done', 'error')
like image 7
Sebastian Viereck Avatar answered Nov 03 '22 05:11

Sebastian Viereck