(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:
$table->string('username');
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, которые тоже будут полезны. Обычно лучше включать их, если только нет какой-то хорошей причины, по которой они будут не нужны. Итак, давайте подумаем об этом. У стандартной статьи будет заголовок и тело. Как насчёт этого? ОК, в таблице у нас строка, которая будет заголовком:
$table->string('title');
И затем ещё одну, но не строку, а целое текстовое поле для тела статьи:
$table->text('body');
(7:30)
И кто знает, может вы захотите что-то ещё, например временной штамп published_at. OК:
$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"
ОК, сейчас, поскольку мы это добавили, мы получили более расширенный шаблон. Хорошо, сделаем наше изменение. Я хочу добавить новый текстовый столбец для отрывка:
$table->text('excerpt');
(10:00)
И теперь, если я хочу отменить это, то мы удалим столбец:
$table->dropColumn('excerpt');
И это, так сказать, формула для того, как отменять наши действия. ОК, я думаю мы готовы к запуску. Ещё один момент тут... будет ли хорошо для нашей таблицы, если у нас будет столбец excerpt, но в нём — ничего? Или, другими словами, при создании новой статьи, можно ли сделать excerpt равным null?
(10:30)
И вы возможно решите, что да, это было бы допустимо.
В этом случае вам стоит добавить PHPnullable()
:
$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)
Отличная работа ребят !
Спасибо за перевод статей. Плюсую каждую как посмотрю. =)
Спасибо за перевод!!!