ENUM в Yii2. Добавление поля и уставновление для него значения по-умолчанию используя миграции

О миграциях в Yii2 я уже писал, поэтому, если вы еще не знакомы с этим чудным механизмом — обязательно к прочтению. А теперь настало время познакомиться ближе с типами полей. Эта статья будет первой в небольшом цикле статей про добавление частоиспользуемых типов полей в Yii2 миграциях.

Всего мы рассмотрим следующие типы полей:

  1. ENUM
  2. INTEGER
  3. VARCHAR
  4. DATETIME
  5. TIMESTAMP
  6. FLOAT

В данной заметке речь пойдет про тип ENUM.

Добавление поля типа ENUM и уставновление для него значения по-умолчанию

И так, переходим в консоль и создаем миграцию под таблицу user:

php yii migrate/create create_user_table

Открываем созданную миграцию и пишем поля, которые хотим добавить

    public function up()
    {
        $this->createTable('user', [
            'id' => $this->primaryKey(),
            'username' => $this->string(),
            'email' => $this->string(),
            'photo' => $this->string(),
            'password_hash' => $this->string(),
            'access_token' => $this->string(),
            'password_reset_token' => $this->string(),
        ]);
    }

Выполнение такой миграции приведет к созданию таблицы user с указанными полями и с соответствующими типами.

Но мы посидели, подумали и решили, что необходимо добавить поле is_active, которое будет отвечать за статус пользователя: активен, заблокирован или удален. Для поля такого формата у нас в БД есть специальный тип ENUM. Увы, пока нормальной поддержки ENUM в миграциях нет — будем делать как получается. Чтобы добавить поле ENUM допишем в нашу миграцию следующую строку (при условии, что вы еще не выполняли описанную выше миграцию)

    public function up()
    {
        $this->createTable('user', [
            ...
            'is_active' => 'ENUM("active", "blocked", "deleted")',
            ...
        ]);
    }

Таким образом мы добавляем в наш список полей поле is_active с типом ENUM и некоторым списком значений. Все работает, но в созданном поле значение по-умолчанию стоит NULL, а нам надо установить active. Поскольку нормального механизма я не нашел, то для этой задачи мы просто создадим обычный sql запрос и внесем небольшие изменения в текущую миграцию.

И так, пропишем в миграцию такой код:

    public function up()
    {
        $this->createTable('user', [
            ...
        ]);

        $sql = "ALTER TABLE user ALTER is_active SET DEFAULT 'active'";
        $this->execute($sql);
    }

Теперь, выполняя миграцию мы получим таблицу user с полем is_active типа ENUM и значением по-умолчанию active.

Значение, которое мы устанавливаем по-умолчанию, должно совпадать с любым значением из указанного ранее списка. Другими словами, указав список доступных значений для ENUM: active/blocked/deleted, мы не сможем указать значение, которого нет в этом списке!

На что стоит еще обратить внимание. Есть такое понятие, как транзакция.

Механизм транзакций доступен только для InnoDB движка. Для MyISAM этот механизм работать НЕ БУДЕТ

Чтобы данная миграция была выполнена корректно — мы и задействуем механизм транзакций. Для этого всего-то необходимо изменить названия двух методов: up > safeUp & down > safeDown:

    public function safeUp()
    {
        $this->createTable('user', [
            ...
        ]);

        // set default value 'active' for `is_active` column
        $sql = "ALTER TABLE user ALTER is_active SET DEFAULT 'active'";
        $this->execute($sql);
    }

    /**
     * @inheritdoc
     */
    public function safeDown()
    {
        $this->dropTable('user');
    }

На этом все.