• Стоит ли использовать типы данных ENUM & SET в БД MySQL?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Set я не использовал, а вот Enum использую успешно. Используется он очень просто. Причём я создаю отдельный класс для каждого enum-а в проекте, что даёт некоторые преимущества, например, простой доступ к массиву допустимых значений.

    Я создаю в проекте папку DBAL, и там создаю такие классы:
    <?php
    
    namespace AppBundle\DBAL;
    
    use Doctrine\DBAL\Types\Type;
    use Doctrine\DBAL\Platforms\AbstractPlatform;
    
    abstract class EnumType extends Type
    {
        protected $name;
    
        public static $VALUES = array();
    
        public static function getValues()
        {
            return array_combine(static::$VALUES, static::$VALUES);
        }
    
        public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
        {
            $values = array_map(function($val) { return "'".$val."'"; }, static::$VALUES);
    
            return "ENUM(".implode(", ", $values).") COMMENT '(DC2Type:".$this->name.")'";
        }
    
        public function convertToPHPValue($value, AbstractPlatform $platform)
        {
            return $value;
        }
    
        public function convertToDatabaseValue($value, AbstractPlatform $platform)
        {
            if (!in_array($value, static::$VALUES)) {
                throw new \InvalidArgumentException("Invalid value '$value' for enum '$this->name'.");
            }
            return $value;
        }
    
        public function getName()
        {
            return $this->name;
        }
    }

    Этот класс является базовым для кастомных классов Enum-ов, вот пример одного такого:
    <?php
    
    namespace AppBundle\DBAL;
    
    class GenderType extends EnumType
    {
        protected $name = 'gender';
        public static $VALUES = array('male', 'female');
    }

    Теперь нужно научить доктрину их использовать:
    doctrine:
        dbal:
            # ...
            types:
                gender: AppBundle\DBAL\GenderType
            mapping_types:
                enum: string
                gender: gender

    Теперь можно использовать в описаниях сущностей:
    <?php
    
    namespace AppBundle\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    use Gedmo\Mapping\Annotation as Gedmo;
    
    /**
     * @ORM\Entity
     */
    class Person
    {
        // other fields
    
        /**
         * @var string
         *
         * @ORM\Column(type="gender")
         */
        protected $gender;
    
        // setters & getters
    }

    И в любом месте кода можно получить список доступных значений:
    foreach (GenderType::$VALUES as $gender) {
        echo $gender;
    }


    Насчёт типа SET - думаю, нужно написать подобный класс, умеющий переводить из значения php в формат sql, который корректно сохранит в поле. Но по мне, для языков лучше использовать simple_array, и не мучаться с ними.
    Ответ написан
    4 комментария