What do you use instead of ENUM in doctrine2?

后端 未结 4 1748
半阙折子戏
半阙折子戏 2021-01-30 13:04

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

相关标签:
4条回答
  • 2021-01-30 13:41

    You should use fre5h/DoctrineEnumBundle for doctrine when using symfony:

    Example of using

    Create a class for new ENUM type BasketballPositionType:

    <?php
    namespace App\DBAL\Types;
    
    use Fresh\DoctrineEnumBundle\DBAL\Types\AbstractEnumType;
    
    final class BasketballPositionType extends AbstractEnumType
    {
        public const POINT_GUARD = 'PG';
        public const SHOOTING_GUARD = 'SG';
        public const SMALL_FORWARD = 'SF';
        public const POWER_FORWARD = 'PF';
        public const CENTER = 'C';
    
        protected static $choices = [
            self::POINT_GUARD => 'Point Guard',
            self::SHOOTING_GUARD => 'Shooting Guard',
            self::SMALL_FORWARD => 'Small Forward',
            self::POWER_FORWARD => 'Power Forward',
            self::CENTER => 'Center'
        ];
    }
    

    Register BasketballPositionType for Doctrine in config.yml:

    doctrine:
        dbal:
            types:
                BasketballPositionType: App\DBAL\Types\BasketballPositionType
    

    Create a Player entity that has a position field:

    <?php
    namespace App\Entity;
    
    use App\DBAL\Types\BasketballPositionType;
    use Doctrine\ORM\Mapping as ORM;
    use Fresh\DoctrineEnumBundle\Validator\Constraints as DoctrineAssert;
    
    /**
     * @ORM\Entity()
     * @ORM\Table(name="players")
     */
    class Player
    {
        /**
         * @ORM\Id
         * @ORM\Column(name="id", type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;
    
        /**
         * Note, that type of a field should be same as you set in Doctrine config
         * (in this case it is BasketballPositionType)
         *
         * @ORM\Column(name="position", type="BasketballPositionType", nullable=false)
         * @DoctrineAssert\Enum(entity="App\DBAL\Types\BasketballPositionType")     
         */
        protected $position;
    
        public function getId()
        {
            return $this->id;
        }
    
        public function setPosition(string $position)
        {
            $this->position = $position;
        }
    
        public function getPosition(): string
        {
            return $this->position;
        }
    }
    

    Now you can set a position for Player inside some action or somewhere else:

    $player->setPosition(BasketballPositionType::POINT_GUARD);
    
    0 讨论(0)
  • 2021-01-30 13:51

    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')
    
    0 讨论(0)
  • 2021-01-30 13:55

    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 # <=======
      
    0 讨论(0)
  • 2021-01-30 13:59

    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.

    0 讨论(0)
提交回复
热议问题