Может войдёшь?
Черновики Написать статью Профиль

Основы Laravel 5: Миграции

перевод Основы Laravel 5 Laracasts

Это перевод видео-урока с Laracasts, серия Laravel 5 Fundamentals, урок №7Migrations от . Перевод обновлён . Опечатка? Выдели и нажми Ctrl+Enter.

(0:00)
Миграции БД — одна из самых мощных особенностей Laravel. Сначала миграция может показаться слегка устрашающей, если вы не знакомы с термином. Вот что я об этом думаю — это как контроль версий для вашей БД. Вспомните, если вам нужна была раньше некая таблица, допустим для статей. Как вы её создавали? И могу поспорить, вот что вы делали... Наверняка открывали какую-нибудь GUI-программу вроде Sequel Pro или похожую на неё.

(0:30)
И затем вы вручную создавали таблицу и определяли столбцы. Хорошо, с этим нет проблем. Но допустим вам нужно добавить второго члена в команду — как им получить ту же настройку вашей БД? Думаю вы экспортируете схему, отправите её им, и затем они импортируют её. Но теперь, что если вы сделали изменение в БД? Может быть вы изменили имя столбца. У нас появились проблемы, ведь все разработчики в вашей команде, особенно если они работают удалённо, должны убедиться, что их состояние БД точно такое же, как у всех.

(1:00)
Так что, как вы можете представить, это может быть довольно сложно. Не говоря уже о факте что ваша производственная БД должна быть также синхронизирована. Что если вместо всего этого мы могли бы предоставить все те же наборы инструкций нашей БД как класс PHP? Какие у этого преимущества? Я вам покажу. Тут есть парочка по умолчанию. Идём в database, migrations... и вы увидите пару включённых здесь.

(1:30)
Одну для создания таблицы users, и одну для password_resets. Теперь запомните, если в вашем приложении нет пользователей, то вы можете их удалить. Они тут не обязательны. Однако в большинстве приложений есть таблица users, так что это может быть очень полезно. Теперь, если вы слегка ошеломлены и думаете: «Я не хочу создавать класс каждый раз как делаю изменения в БД. Это слишком долго.» На самом деле — нет. Laravel содержит несколько генераторов, которые сильно ускоряют всё это дело.

(2:00)
Учитывая это, давайте посмотрим. У нас есть два метода, PHPup() и PHPdown(). Так, значит для нашего метода PHPup(), какие действия нам нужно предпринять? В нашем случае, мы создаём новую таблицу users. И мы планируем эту таблицу так: ID c автоматическим увеличением (autoincrementing), имя — строка, email — уникальная строка, пароль — 60 символов, PHPrememberToken() — он немного особенный, но пока не думайте о нём.

(2:30)
А также несколько временных штампов — когда этот пользователь был создан, когда последний раз обновлён. Но теперь, как насчёт метода PHPdown()? Вот одна из отличных вещей насчёт миграции. Допустим вы запустили миграцию для создания этой таблицы users. Но затем, через 20 минут, вы осознали: «Ой, это должно быть username, а не name Что же, это довольно легко исправить.
Всё что необходимо сделать — это откатить миграцию назад.

(3:00)
Я покажу вам как это сделать. Делаете изменение, перезапускаете миграцию, и готово! Больше ничего не нужно делать. Даже лучше, такие изменения и модификации являются частью вашей системы контроля версий, что очень даже круто. Но давайте оставим здесь просто name. Теперь, у нас есть миграция, но значит ли это, что у нас уже есть таблица users? Нет. Мы создали класс, но ещё не «мигрировали» БД. Давайте попробуем сделать это:

shphp artisan migrate

(3:30)
И готово. Мы создали таблицы users и password_resets. Теперь давайте копнём глубже и посмотрим как это выглядит. Позволю себе предположить что на вашей машине уже установлен SQLite. Скорее всего он у вас есть. Если же нет, то вы можете проверить, запустив sqlite3, и у вас должен выскочить запрос типа такого. Иначе, если вы Мак-пользователь, обратите внимание на Homebrew. Он позволит вам сделать:

shhomebrew install sqlite

(4:00)
Очень полезно, и это же применимо для многих прочих мелких инструментов и компонентов, которые вы можете подтянуть. И конечно же, если вы повторяете все действия, но по какой-то причине не можете установить что-либо на своём компьютере — оставьте комментарий ниже и мы все постараемся помочь вам.
Хорошо, давайте попробуем:

shsqlite3 storage/database.sqlite

(я укажу путь к файлу).
Хорошо, теперь посмотрим на таблицы:

.tables

И вы увидите что у нас есть таблица migrations. Её никогда не нужно трогать. Фреймворк Laravel использует её, чтобы решить есть ли новые классы миграции, которые нужно запустить, что требуется откатить, вещи типа того.

(4:30)
Но дальше у нас есть две созданные таблицы. Давайте посмотрим их структуру:

.schema

И вы увидите обычный SQL-текст:

sqlCREATE TABLE "users"

и все эти поля были сгенерированы Laravel, основываясь на созданном нами классе миграции. Теперь вернёмся к тому примеру где мы говорили: "Что если мы дали название name, а должно быть username? Что нам сделать чтобы исправить это? " Я открою новую вкладку терминала и скажу:

shphp artisan

(5:00)
Сначала дайте я вам покажу. Если я запущу эту строку, то вы увидите все возможные команды, которые можете запустить. В основном вы будете использовать вот эти три (migrate:refresh, migrate:reset, migrate:rollback).
Итак, я хочу откатить назад последнюю миграцию:

shphp artisan migrate:rollback

Считайте что это работает как «undo» (вернуться на шаг назад). Я только что запустил миграцию, но допустил ошибку и собираюсь откатить назад, поправить её и затем перезапустить миграцию. Теперь поправим ошибку. Исправим тут на username:

PHP
$table->string('username');

(5:30)
Вернёмся и запустим:

shphp artisan migrate

И мы закончили. БД обновилась. Чтобы доказать вам:

shsqlite3 storage/database.sqlite
.schema

Мы можем снова посмотреть на структуру. И теперь вы видите как изменения отражены здесь. Довольно круто, правда? Теперь, когда вы понимаете как запускать миграции и откатывать их, как насчёт создания новых? ОК, давайте продолжим с той простой идеей о статье. Мы хотим таблицу, чтобы хранить там все статьи вашего блога.

(6:00)
Очень просто. Давайте скажем:

shphp artisan make:migration

(я хочу создать новую миграцию)
Не забывайте, что если вдруг забудете какие аргументы писать или в каком порядке, то просто перед этим добавьте help:

shphp artisan help make:migration

Важный момент вот здесь — имя миграции. Считайте что это идентификатор для описания того, что эта миграция делает. Так, если я создаю таблицу articles, то имя может быть: create_articles_table.

(6:30)
Далее, вы увидите тут пару флагов, и они просто регулируют шаблон, который будет применяться при генерации вашего файла. Давайте попробуем:

shphp artisan make:migration create_articles_table

И раз я создаю таблицу, то передаю: --create="articles".
Хорошо, давайте запустим это. И вот, я создал эту новую миграцию. Давайте рассмотрим её. В боковой панели вы увидите, что вот она, новая, здесь. И даже лучше, для нас был создан хороший шаблон.

(7:00)
Он предполагает, что вы хотите ID с авто приращением (довольно типично для таблиц). Также временные штампы created_at и updated_at, которые тоже будут полезны. Обычно лучше включать их, если только нет какой-то хорошей причины, по которой они будут не нужны. Итак, давайте подумаем об этом. У стандартной статьи будет заголовок и тело. Как насчёт этого? ОК, в таблице у нас строка, которая будет заголовком:

PHP
$table->string('title');

И затем ещё одну, но не строку, а целое текстовое поле для тела статьи:

PHP
$table->text('body');

(7:30)
И кто знает, может вы захотите что-то ещё, например временной штамп published_at. OК:

PHP
$table->timestamp('published_at');

Таким образом, логика здесь диктует: «Я могу запланировать тут статью, но если published_at не равна сегодняшнему дню или моменту в прошлом, то не нужно отражать эту статью». ОК, вот так мы создаём таблицу.
Для метода PHPdown(), мы таким образом отменяем создание.

(8:00)
В этом случае мы удалим таблицу articles. Но в других случаях вы должны откатить изменения, изменив таблицу. И скоро я покажу вам, как это выглядит. Сейчас же, наша миграция хорошо выглядит, так давайте мигрируем БД:

shphp artisan migrate

И всё готово. У вас тут новая таблица. Дальше, если вам нужно сделать изменение, и особенно если вы ещё не внесли ваши изменения в производственную версию, то я советую просто откатиться, сделать модификации и перезапуститься.

(8:30)
Но давайте представим, что вы уже это сделали и пути назад нет. И теперь мы решили, что нам нужно добавить в эту таблицу новый столбец. Мы можем создать новую миграцию. Вот так:

shphp artisan make:migration

И опять, ID здесь (или имя миграции), вам нужно чётко описать, что именно вы делаете. И это хороший принцип, которого стоит придерживаться.

(9:00)
Почему бы нам не сказать тут, что для вашей статьи вы также хотите добавить новый столбец? Возможно что-то типа отрывка из статьи (excerpt). Итак, excerpt будет отображаться на основной странице, и когда вы кликнете на статью, то перейдёте к полному тексту. Хорошо, мы хотим добавить отрывок к таблице articles:

add_excerpt_to_articles_table

Сделано. Давайте посмотрим, как она теперь выглядит. У нас есть новая миграция, но она немного другая.

(9:30)
И заметьте, в этом случае, у нас не так много шаблонного кода. Да, можно было бы написать всё это вручную, и это бы не заняло много времени. Но если мы можем попросить Laravel сделать это за нас, то почему бы и нет? Давайте запустим команду ещё раз, но сейчас я скажу Laravel с какой таблицей я работаю:

--table="articles"

ОК, сейчас, поскольку мы это добавили, мы получили более расширенный шаблон. Хорошо, сделаем наше изменение. Я хочу добавить новый текстовый столбец для отрывка:

PHP
$table->text('excerpt');

(10:00)
И теперь, если я хочу отменить это, то мы удалим столбец:

PHP
$table->dropColumn('excerpt');

И это, так сказать, формула для того, как отменять наши действия. ОК, я думаю мы готовы к запуску. Ещё один момент тут... будет ли хорошо для нашей таблицы, если у нас будет столбец excerpt, но в нём — ничего? Или, другими словами, при создании новой статьи, можно ли сделать excerpt равным null?

(10:30)
И вы возможно решите, что да, это было бы допустимо.
В этом случае вам стоит добавить PHPnullable():

PHP
$table->text('excerpt')->nullable();

Дальше:

shphp artisan migrate

И мы всё сделали. Теперь у нас есть наш столбец excerpt в нашей таблице articles. Давайте убедимся. Мы запускаем это, рассматриваем структуру, и вот тут внизу наш «отрывок». Но тут есть один моментик, о котором я хочу вас предупредить.

(11:00)
Давайте откатим миграцию просто ради шутки и посмотрим что произойдёт:

shphp artisan migrate:rollback

И, блин, всё сломалось. Если мы прокрутим сюда наверх, то увидим, что Laravel пытался сослаться на этот класс (PHPDoctrine\DBAL\Driver\PDOSqlite\Driver), но не смог его найти. И это потому, что если вы хотите удалить столбец, то нужен специальный пакет. И документация Laravel расскажет вам всё что нужно. Достаточно лишь выполнить:

shcomposer require doctrine/dbal

Так давайте подтянем его и дадим секунду на установку.

(11:30)
Готово. Пробуем снова. Откатываем миграцию, и сейчас всё работает. Так что помните об этом. И теперь опять если мы посмотрим структуру (schema), то увидим, что изменения отображены. Нашего excerpt больше нет.
Хорошо, теперь, когда вы понимаете основы миграций, в следующем эпизоде, я познакомлю вас с Eloquent, который вы полюбите.

Как вы считаете, полезен ли этот материал? Да Нет

Комментарии (3)

Gilfoyle

Отличная работа ребят !

StrikS

Спасибо за перевод статей. Плюсую каждую как посмотрю. =)

PashaKiev

Спасибо за перевод!!!

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.