mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-07 00:26:52 +01:00
348 lines
19 KiB
Plaintext
348 lines
19 KiB
Plaintext
Міграції
|
||
========
|
||
|
||
> Note|Примітка: Міграції доступні з версії 1.1.6.
|
||
|
||
Як і початковий код, структура бази даних змінюється в процесі розробки та підтримки додатку.
|
||
Приміром, під час розробки може знадобитися додати нову таблицю або вже після розміщення додатка на сервері додати індекс або стовпець.
|
||
При цьому важливо відстежувати зміни в структурі бази даних (звані **міграціями**) також, як ми робимо це для нашого початкового коду.
|
||
Якщо початковий код і база даних не відповідають один одному, швидше за все все додаток не буде працювати.
|
||
Саме тому в Yii є підтримка міграцій, що дозволяє відстежувати зміни в базі даних, застосовувати міграції або відкочувати вже застосовані.
|
||
|
||
Нижче наведено поетапний процес як ми можемо використовувати міграції бази даних при розробці:
|
||
|
||
1. Олександр створює нову міграцію (наприклад, створює нову таблицю).
|
||
2. Олександр заливає її в систему контролю версій (SVN, GIT або іншу).
|
||
3. Павло оновлюється із системи контролю версій і отримує нову міграцію.
|
||
4. Павло застосовує міграцію до своєї локальної бази даних.
|
||
|
||
У Yii управління міграціями проводиться через консольну команду `yiic migrate`, яка підтримує створення нових міграцій,
|
||
застосування, відкат і повторне застосування міграцій, перегляд історії міграцій і нових міграцій.
|
||
|
||
> Note|Примітка: При роботі з командою `migrate` рекомендується використовувати yiic програми (тобто після `cd path/to/protected`),
|
||
а не yiic з директорії `framework`. Переконайтеся, що директорія `protected/migrations` існує і доступна для запису.
|
||
Також перевірте налаштування зʼєднання з базою даних в `protected/config/console.php`.
|
||
|
||
Створення міграцій
|
||
------------------
|
||
|
||
Для створення нової міграції (наприклад, яка створює таблицю для новин), ми повинні ввести в консолі:
|
||
|
||
~~~
|
||
yiic migrate create <name>
|
||
~~~
|
||
|
||
Обовʼязковий параметр `name` повинен містити дуже короткий опис міграції (таке, як, наприклад, `create_news_table`).
|
||
Як буде показано далі, цей параметр використовується як частина імені класу міграції,
|
||
тому використовувати можна тільки букви, цифри та знаки підкреслення.
|
||
|
||
~~~
|
||
yiic migrate create create_news_table
|
||
~~~
|
||
|
||
Наведена команда створить в директорії `protected/migrations` файл `m101129_185401_create_news_table.php`, який містить наступне:
|
||
|
||
~~~
|
||
[php]
|
||
class m101129_185401_create_news_table extends CDbMigration
|
||
{
|
||
public function up()
|
||
{
|
||
}
|
||
|
||
|
||
public function down()
|
||
{
|
||
echo "m101129_185401_create_news_table does not support migration down.\n";
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
// якщо потрібно виконати зміни в транзакції, використовуйте safeUp/safeDown
|
||
// замість up/down
|
||
public function safeUp()
|
||
{
|
||
}
|
||
|
||
public function safeDown()
|
||
{
|
||
}
|
||
*/
|
||
}
|
||
~~~
|
||
|
||
Варто відзначити, що імʼя класу збігається з іменем файлу і будується як `m<timestamp>_<name>`,
|
||
де `<timestamp>` — це час створення міграції в UTC (у форматі `yymmdd_hhmmss`), а `<name>` — те, що передано в параметрі `name` команди.
|
||
|
||
Метод `up()` повинен містити код, який виконує міграцію, а метод `down()` може містити код, який скасовує зроблене в `up()`.
|
||
|
||
Іноді реалізувати `down()` не виходить. Приміром, якщо в `up()` із таблиці видаляються дані, в `down()` повернути їх не вийде.
|
||
У цьому випадку міграція називається незворотною, що означає неможливість повернення до попереднього стану бази даних.
|
||
У наведеному вище коді метод `down()` повертає `false`. Це означає неможливість відкату міграції.
|
||
|
||
> Info|Інформація: Починаючи з версії 1.1.7, якщо метод `up()` або метод `down()` повертають `false`,
|
||
всі наступні міграції не будуть застосовані. В 1.1.6 для цього було необхідно викинути виняток.
|
||
|
||
Розглянемо як приклад міграцію, яка створює таблицю з новинами.
|
||
|
||
~~~
|
||
[php]
|
||
class m101129_185401_create_news_table extends CDbMigration
|
||
{
|
||
public function up()
|
||
{
|
||
$this->createTable('tbl_news', array(
|
||
'id' => 'pk',
|
||
'title' => 'string NOT NULL',
|
||
'content' => 'text',
|
||
));
|
||
}
|
||
|
||
public function down()
|
||
{
|
||
$this->dropTable('tbl_news');
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Базовий клас [CDbMigration] надає набір методів для роботи з даними і структурою бази даних.
|
||
Приміром, за допомогою [CDbMigration::createTable] можна створити нову таблицю, а [CDbMigration::insert] додасть рядок з даними.
|
||
Всі ці методи використовують підключення до бази даних, що повертає [CDbMigration::getDbConnection()],
|
||
що за замовчуванням еквівалентно `Yii::app()->db`.
|
||
|
||
> Info|Інформація: Як ви могли помітити, методи [CDbMigration] дуже схожі на методи [CDbCommand].
|
||
І це насправді так. Єдина відмінність у тому, що методи [CDbMigration] підраховують витрачений час
|
||
на їх виконання і виводять повідомлення про параметри методів.
|
||
|
||
Транзакційні міграції
|
||
---------------------
|
||
|
||
> Info|Інформація: Дана можливість підтримується починаючи з версії 1.1.7.
|
||
|
||
При застосуванні складних міграцій для дотримання цілісності та звʼязності потрібно або виконати всі запити, або,
|
||
якщо запит не виконався, скасувати попередні запити. Для досягнення цієї мети можна використовувати транзакції.
|
||
|
||
Можна почати транзакцію явно і заключити в неї весь код, який змінює базу даних:
|
||
|
||
~~~
|
||
[php]
|
||
class m101129_185401_create_news_table extends CDbMigration
|
||
{
|
||
public function up()
|
||
{
|
||
$transaction=$this->getDbConnection()->beginTransaction();
|
||
try
|
||
{
|
||
$this->createTable('tbl_news', array(
|
||
'id' => 'pk',
|
||
'title' => 'string NOT NULL',
|
||
'content' => 'text',
|
||
));
|
||
$transaction->commit();
|
||
}
|
||
catch(Exception $e)
|
||
{
|
||
echo "Exception: ".$e->getMessage()."\n";
|
||
$transaction->rollback();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// …схожий код для down()
|
||
}
|
||
~~~
|
||
|
||
А можна зробити це простіше, реалізувавши метод `safeUp()` замість `up()` і `safeDown()` замість `down()`:
|
||
|
||
~~~
|
||
[php]
|
||
class m101129_185401_create_news_table extends CDbMigration
|
||
{
|
||
public function safeUp()
|
||
{
|
||
$this->createTable('tbl_news', array(
|
||
'id' => 'pk',
|
||
'title' => 'string NOT NULL',
|
||
'content' => 'text',
|
||
));
|
||
}
|
||
|
||
public function safeDown()
|
||
{
|
||
$this->dropTable('tbl_news');
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Yii при застосуванні міграції почне транзакцію і, потім, виконає код в `safeUp()` або `safeDown()`.
|
||
Якщо при цьому виникне яка-небудь помилка, відбудеться відкат транзакції, тобто база повернеться у початковий стан.
|
||
|
||
> Note|Примітка: Не всі СУБД повністю підтримують транзакції і не для всіх виразів. У тому випадку,
|
||
якщо підтримки транзакцій немає, реалізовувати треба `up()` і `down()`.
|
||
У разі MySQL та MariaDB, деякі вирази SQL можуть викликати неявне застосування транзакції
|
||
(детальніше про це у документації до [MySQL](http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html)
|
||
та [MariaDB](https://mariadb.com/kb/en/sql-statements-that-cause-an-implicit-commit/)).
|
||
|
||
Застосування міграцій
|
||
---------------------
|
||
|
||
Для того, щоб застосувати всі нові міграції (тобто привести локальну БД в актуальний стан), слід запустити наступну команду:
|
||
|
||
~~~
|
||
yiic migrate
|
||
~~~
|
||
|
||
Команда відобразить перелік всіх нових міграцій і, у випадку позитивної відповіді,
|
||
по черзі запустить метод `up()` у кожному класі міграції в порядку його створення.
|
||
|
||
Після застосування міграції у таблицю `tbl_migration` буде внесений відповідний запис.
|
||
Це дозволяє дізнатися, які міграції вже застосовані, а які ні. Якщо таблиця `tbl_migration` не існує,
|
||
вона буде створена автоматично в базі даних, зазначеної у компоненті `db` додатка.
|
||
|
||
Іноді потрібно застосувати лише одну або декілька нових міграцій. Для цього можна використовувати наступну команду:
|
||
|
||
~~~
|
||
yiic migrate up 3
|
||
~~~
|
||
|
||
При цьому застосовується три нові міграції. Замість трьох можна вказати будь-яку кількість застосовуваних міграцій.
|
||
|
||
Також можна привести стан бази даних до певної версії:
|
||
|
||
~~~
|
||
yiic migrate to 101129_185401
|
||
~~~
|
||
|
||
У якості параметра, що вказує версію, до якої потрібно привести базу даних, використовується частина імені файлу,
|
||
що відповідає часу створення міграції. Якщо між останньою застосованою і вказаною міграціями кілька міграцій,
|
||
то всі вони будуть застосовані. Якщо зазначена міграція вже застосовувалася, то буде проведений відкат всіх міграцій,
|
||
застосованих після неї (описано в наступному розділі).
|
||
|
||
Відкат міграцій
|
||
---------------
|
||
|
||
Для відкату однієї або декількох останніх застосованих міграцій можна скористатися наступною командою:
|
||
|
||
~~~
|
||
yiic migrate down [step]
|
||
~~~
|
||
|
||
де необовʼязковий параметр `step` задає кількість міграцій, які треба відкотити.
|
||
За замовчуванням відкочується одна остання застосована міграція.
|
||
|
||
Як було описано раніше, не всі міграції можна відкотити.
|
||
При спробі відкату таких міграцій буде викинуто виключення і процес відкату буде перерваний.
|
||
|
||
Повторне застосування міграцій
|
||
------------------------------
|
||
|
||
Повторне застосування міграції проводиться шляхом послідовного відкату і застосування.
|
||
Здійснити це можна наступною командою:
|
||
|
||
~~~
|
||
yiic migrate redo [step]
|
||
~~~
|
||
|
||
де необовʼязковий параметр `step` вказує кількість міграцій, які необхідно застосувати ще раз.
|
||
За замовчуванням повторюється одна остання міграція.
|
||
|
||
Перегляд інформації про міграції
|
||
--------------------------------
|
||
|
||
Крім застосування і відкату міграцій, інструмент міграцій може відображати історію міграцій і нові, ще не застосовані міграції.
|
||
|
||
~~~
|
||
yiic migrate history [limit]
|
||
yiic migrate new [limit]
|
||
~~~
|
||
|
||
Тут параметр `limit` вказує кількість міграцій, що відображаються. Якщо `limit` не вказаний, відображаються всі міграції.
|
||
|
||
Перша команда показує вже застосовані міграції, друга - міграції, які ще не були застосовані.
|
||
|
||
Зміна історії міграцій
|
||
----------------------
|
||
|
||
Іноді потрібно змінити історію міграцій так, щоб поточна версія була замінена на вказану без застосування або відкату міграцій.
|
||
Часто це потрібно при створенні нової міграції. Для цього можна використовувати наступну команду:
|
||
|
||
~~~
|
||
yiic migrate mark 101129_185401
|
||
~~~
|
||
|
||
Ця команда дуже схожа на `yiic migrate to`, але вона лише змінює таблицю історії міграцій до зазначеної
|
||
версії без застосування або відкату самих міграцій.
|
||
|
||
Налаштування команди міграцій
|
||
-----------------------------
|
||
|
||
Є кілька способів налаштувати команду міграцій.
|
||
|
||
### Використовуючи параметри командного рядка
|
||
|
||
Команда міграцій може бути налаштована чотирма опціями:
|
||
|
||
* `interactive`: чи використовувати інтерактивний режим. За замовчуванням true, тобто при застосуванні міграції буде виводитися підтвердження.
|
||
Якщо параметр виставлений у false, то міграції можна застосувати у фоновому режимі;
|
||
|
||
* `migrationPath`: вказує директорію, в якій зберігаються всі файли міграцій. Шлях повинен вказуватися у форматі псевдоніма
|
||
і відповідна йому директорія повинна існувати. Якщо параметр не вказаний,
|
||
буде використана піддиректорії `migrations`, що знаходиться всередині директорії з додатком;
|
||
|
||
* `migrationTable`: вказує імʼя таблиці в базі даних, яка зберігає історію міграцій. За замовчуванням воно дорівнює `tbl_migration`.
|
||
Структура таблиці наступна: `version varchar(255) primary key, apply_time integer`;
|
||
|
||
* `connectionID`: вказує ідентифікатор компонента бази даних. За умовчанням це 'db';
|
||
|
||
* `templateFile`: вказує шлях до файлу, який використовується як шаблон для генерації класів міграцій.
|
||
Шлях повинен вказуватися як псевдонім (тобто як `application.migrations.template`).
|
||
Якщо шлях не заданий, буде використовуватися внутрішній шаблон.
|
||
У шаблоні токен `{ClassName}` буде замінений імʼям класу міграції.
|
||
|
||
Для зазначення опцій використовується наступний формат:
|
||
|
||
~~~
|
||
yiic migrate up --option1=value1 --option2=value2 ...
|
||
~~~
|
||
|
||
Наприклад, якщо необхідно мігрувати модуль `forum`, файли міграцій якого розташовані у директорії модуля `migrations`,
|
||
можна скористатися наступною командою:
|
||
|
||
~~~
|
||
yiic migrate up --migrationPath=ext.forum.migrations
|
||
~~~
|
||
|
||
Варто відзначити, що при передачі через командний рядок прапорів,
|
||
таких як `interactive`, необхідно використовувати значення `1` або `0`:
|
||
|
||
~~~
|
||
yiic migrate --interactive=0
|
||
~~~
|
||
|
||
### Глобальна конфігурація команди
|
||
|
||
У той час, як опції командного рядка дозволяють нам на льоту конфігурувати команду міграцій,
|
||
іноді потрібно застосувати налаштування раз і назавжди.
|
||
Приміром, нам може знадобитися використовувати іншу таблицю для зберігання історії міграцій або використовувати свій шаблон міграції.
|
||
Це можна зробити, змінивши налаштування консольного додатку наступним чином:
|
||
|
||
~~~
|
||
[php]
|
||
return array(
|
||
......
|
||
'commandMap'=>array(
|
||
'migrate'=>array(
|
||
'class'=>'system.cli.commands.MigrateCommand',
|
||
'migrationPath'=>'application.migrations',
|
||
'migrationTable'=>'tbl_migration',
|
||
'connectionID'=>'db',
|
||
'templateFile'=>'application.migrations.template',
|
||
),
|
||
......
|
||
),
|
||
......
|
||
);
|
||
~~~
|
||
|
||
Тепер, при запуску команди `migrate`, зазначені вище налаштування будуть застосовані
|
||
без введення яких-небудь додаткових параметрів. |