Миграции и пополнения — это мощные утилиты для базы данных, предоставляемые PHP-фреймворком Laravel, которые позволяют разработчикам быстро инициализировать, уничтожать и воссоздавать базу данных приложения. Эти утилиты помогают свести к минимуму проблемы несогласованности базы данных, которые могут возникать, когда несколько разработчиков работают над одним приложением: новым участникам нужно будет запустить всего несколько команд artisan
для настройки базы данных при новой установке.
В этом обучающем руководстве мы выполним миграцию и пополнения для заполнения базы данных демонстрационного приложения Laravel, используя примеры данных. В конце вы сможете уничтожать и воссоздавать таблицы базы данных в любой момент времени, пользуясь только командами artisan
.
Для выполнения этого обучающего руководства вам потребуется следующее:
Примечание. В этом обучающем руководстве мы будем использовать контейнеризованную среду разработки под управлением Docker Compose для запуска приложения, но вы можете использовать приложение на сервере LEMP. Чтобы воспользоваться этим вариантом, ознакомьтесь с нашим руководством по установке и настройке Laravel с LEMP в Ubuntu 18.04.
Вначале мы получим демонстрационное приложение Laravel из репозитория GitHub. Нас интересует раздел tutorial-02
, который содержит настройку Docker Compose для запуска приложения в контейнерах. В данном примере мы загрузим приложение в домашнюю папку, но вы можете использовать любую директорию по вашему выбору:
- cd ~
- curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-2.0.1.zip -o travellist.zip
Поскольку мы загрузили код приложения в виде файла .zip
, нам нужно воспользоваться командой unzip
для распаковки архива. Если вы не использовали эту программу в последнее время, обновите локальный индекс пакетов вашего компьютера:
- sudo apt update
Затем выполните установку пакета unzip
:
- sudo apt install unzip
Распакуйте содержимое приложения:
- unzip travellist.zip
Далее необходимо переименовать директорию на travellist-demo для удобства доступа:
- mv travellist-laravel-demo-tutorial-2.0.1 travellist-demo
На следующем шаге мы создадим файл конфигурации .env
для настройки приложения.
.env
приложенияВ Laravel файл .env
используется для настройки зависимых от среды конфигураций, например, учетных данных и любой информации, которая может отличаться для разных развертываний. Этот файл не включен в систему контроля версий.
Предупреждение. Файл конфигурации среды содержит важную информацию о вашем сервере, включая учетные данные базы данных и ключи безопасности. В связи с этим не следует предоставлять этот файл в открытый доступ.
Значения в файле .env
имеют приоритет по отношению к значениям в обычных файлах конфигурации, расположенных в директории config
. Для каждого случая установки в новую среду требуется персонализированный файл среды, где будут определены такие настройки, как параметры подключения к базе данных, параметры отладки, URL приложения и другие параметры, в зависимости от используемой для запуска приложения среды.
Перейдите в директорию travellist-demo
:
- cd travellist-demo
Теперь мы создадим новый файл .env
для настройки индивидуальных параметров конфигурации для создаваемой нами среды разработки. В комплектацию Laravel входит образец файла .env
, который мы скопируем для создания собственного файла:
- cp .env.example .env
Откройте этот файл с помощью nano
или другого текстового редактора на ваш выбор:
- nano .env
Теперь ваш файл .env
выглядит следующим образом:
APP_NAME=Travellist
APP_ENV=dev
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost:8000
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=travellist
DB_USERNAME=travellist_user
DB_PASSWORD=password
…
Текущий файл .env
для демонстрационного приложе
ния travellist содержит настройки для работы в контейнеризованной среде, которую мы создали с помощью Docker Compose в последней статье данной серии. Вам не обязательно вносить изменения в эти значения, но вы можете изменить значения DB_DATABASE
, DB_USERNAME
и DB_PASSWORD
, если захотите, так как они автоматически подставляются из нашего файла docker-compose.yml
для настройки базы данных разработки. Убедитесь, что переменная DB_HOST
остается без изменений, поскольку она указывает имя нашей службы базы данных в среде Docker Compose.
При внесении любых изменений в файл обязательно сохраните и закройте его, нажав CTRL + X
, Y
, а затем ENTER
.
Примечание. Если вы хотите запустить приложение на сервере LEMP, вам нужно изменить выделенные значения в соответствии с собственными настройками базы данных, включая значение переменной DB_HOST
.
Теперь мы воспользуемся Composer, инструментом для управления зависимостями PHP, чтобы установить зависимости приложения и обеспечить возможность выполнения команд artisan
.
Сформируйте вашу среду Docker Compose с помощью следующей команды. В результате будет создан образ travellist
для службы app
и добавлены дополнительные образы Docker, необходимые службам nginx
и db
, чтобы создать среду приложения:
- docker-compose up -d
OutputCreating network "travellist-demo_travellist" with driver "bridge"
Building app
Step 1/11 : FROM php:7.4-fpm
---> fa37bd6db22a
Step 2/11 : ARG user
---> Running in 9259bb2ac034
…
Creating travellist-app ... done
Creating travellist-nginx ... done
Creating travellist-db ... done
Выполнение этой операции может занять несколько минут. После завершения процесса мы сможем запустить Composer для установки зависимостей приложения.
Для выполнения composer
и других команд в контейнере службы app
мы будем использовать docker-compose exec
. Команда exec
позволяет нам выполнять любую команду по нашему выбору в контейнерах под управлением Docker Compose. Она имеет следующий синтаксис: docker-compose exec service_name command
.
Примечание. Если вы предпочитаете использовать сервер LEMP для запуска демонстрационного приложения, можно проигнорировать часть docker-compose exec app
для команд, представленных в рамках этого руководства. Например, вместо запуска следующей команды, как она написана, вы можете использовать следующую команду:
- composer install
Чтобы выполнить установку composer
в контейнер приложения
, запустите следующую команду:
- docker-compose exec app composer install
OutputLoading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 85 installs, 0 updates, 0 removals
- Installing doctrine/inflector (1.3.1): Downloading (100%)
- Installing doctrine/lexer (1.2.0): Downloading (100%)
- Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%)
…
Когда Composer выполнит установку зависимостей приложения, вы сможете выполнять команды artisan
. Чтобы убедиться, что приложение сможет подключиться к базе данных, выполните следующую команду, которая выполняет очистку всех существующих таблиц:
- docker-compose exec app php artisan db:wipe
Эта команда будет удалять все ранее существовавшие таблицы в настроенной базе данных. Если выполнение команды было завершено успешно, а приложению удалось подключиться к базе данных, вы увидите следующий результат:
OutputDropped all tables successfully.
Теперь, когда вы установили зависимости приложения с помощью Composer, вы можете использовать инструмент artisan
для создания миграций и пополнений.
Инструмент командной строки artisan
, предоставляемый вместе с Laravel, содержит ряд вспомогательных команд, которые могут использоваться для управления приложением и загрузки новых классов. Чтобы сгенерировать новый класс миграции, мы можем использовать команду make:migration
следующим образом:
- docker-compose exec app php artisan make:migration create_places_table
Laravel выводит операцию, которую необходимо выполнить (create
), имя таблицы (places
), а также то, будет ли эта миграция создавать новую таблицу или нет, на основе описательного имени, предоставленного команде make:migration
.
Вывод будет выглядеть следующим образом:
OutputCreated Migration: 2020_02_03_143622_create_places_table
В результате будет создан новый файл в директории database/migrations
приложения. Отметка времени, которая включается в автоматически генерируемый файл, используется Laravel для определения того, в каком порядке следует выполнять миграции.
Используйте предпочитаемый вами текстовый редактор для открытия сгенерированного файла миграции. Обязательно замените выделенное значение на имя вашего файла миграции:
- nano database/migrations/2020_02_03_143622_create_places_table.php
Сгенерированный файл миграции содержит класс CreatePlacesTable
:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePlacesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('places', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('places');
}
}
Этот класс имеет два метода: up
и down
. Оба метода содержат код начальной загрузки, который вы можете расширить, чтобы настроить то, что будет происходить, когда эта миграция выполняется, а также что будет происходить в случае отката изменений.
Мы изменим метод up
так, чтобы таблица places
имела структуру, которую мы уже использовали в текущей версии приложения:
id
: поле первичного ключа.name
: название места.visited
: было ли посещено это место или нет.Конструктор схемы Laravel предоставляет методы для создания, обновления и удаления таблиц в базе данных. Класс Blueprint
определяет структуру таблицы и предоставляет несколько методов для абстракции определения каждого поля таблицы.
Автоматически генерируемый код задает поле основного идентификатора id
. Метод timestamps
создает два поля datetime
, которые автоматически обновляются классами соответствующей базы данных, когда данные помещаются в таблицу или обновляются. Помимо этого, нам потребуется добавить поля name
и visited
.
Наше поле name
будет иметь тип string
, а для поля visited
будет установлен тип boolean
. Также мы зададим значение по умолчанию 0
для поля visited
, так что если значение не будет передано, это будет означать, что место пока не посещено. Вот как в настоящий момент выглядит метод up
:
…
public function up()
{
Schema::create('places', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name', 100);
$table->boolean('visited')->default(0);
$table->timestamps();
});
}
…
Примечание. Вы можете найти полный список доступных типов столбцов в документации Laravel.
После добавления двух выделенных строк в вашем скрипте миграции сохраните и закройте файл.
Теперь ваша миграция готова к исполнению с помощью artisan migrate
. Однако в этом случае будет создана пустая таблица, а нам нужна возможность добавления примеров данных для разработки и тестирования. На следующем шаге мы узнаем, как сделать это с помощью пополнений базы данных.
seeder — это специальный класс, используемый для генерации и вставки примеров данных в базу данных. Это очень важная функция для среды разработки, поскольку она позволяет воссоздать приложение с новой базой данных, используя примеры значений, которые вам в ином случае пришлось бы вручную вставлять при каждом воссоздании базы данных.
Теперь мы воспользуемся командой artisan
, которая генерирует новый класс seeder для нашей таблицы places
с названием PlacesTableSeeder
:
- docker-compose exec app php artisan make:seeder PlacesTableSeeder
Команда будет создавать новый файл с именем PlacesTableSeeder.php
внутри директории database/seeds
. Откройте этот файл в текстовом редакторе по выбору:
- nano database/seeds/PlacesTableSeeder.php
Вот как выглядит автоматически сгенерированный файл PlacesTableSeeder.php
:
<?php
use Illuminate\Database\Seeder;
class PlacesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
//
}
}
Наш новый класс seeder содержит пустой метод с именем run
. Этот метод будет вызываться при выполнении команды db:seed
Artisan.
Нам нужно изменить метод run
, чтобы включить инструкции по вставке примеров данных в базу данных. Мы воспользуемся конструктором запросов Laravel для организации этого процесса.
Конструктор запросов Laravel предоставляет гибкий интерфейс для операций с базами данных, например, для вставки, обновления и восстановления данных. Также он обеспечивает защиту от внедрения SQL-кода. Конструктор запросов определяется фасадом DB
, статическим прокси для классов базы данных в контейнере службы.
Для начала мы создадим переменную статического класса, хранящую все примеры мест, которые мы хотим вставить в базу данных в форме массива. Это позволит нам использовать цикл foreach
для итерации по всем значениям, вставляя все эти значения в базу данных с помощью конструктора запросов.
Мы назовем эту переменную $places
:
<?php
use Illuminate\Database\Seeder;
class PlacesTableSeeder extends Seeder
{
static $places = [
'Berlin',
'Budapest',
'Cincinnati',
'Denver',
'Helsinki',
'Lisbon',
'Moscow',
'Nairobi',
'Oslo',
'Rio',
'Tokyo'
];
…
Далее нам потребуется включить оператор use
сверху класса PlacesTableSeeder,
чтобы проще ссылаться на фасад DB
в коде:
<?php
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class PlacesTableSeeder extends Seeder
…
Теперь мы можем пробежаться по значениям массива $places
с помощью цикла foreach
и добавить их в нашу таблицу places
с помощью конструктора запросов:
…
public function run()
{
foreach (self::$places as $place) {
DB::table('places')->insert([
'name' => $place,
'visited' => rand(0,1) == 1
]);
}
}
Цикл foreach
проходит по каждому значению статического массива $places
. В каждой итерации мы используем фасад DB
для добавления новой строки в таблице places
. Мы сохраним в поле name
название места, которое мы только что получили из массива $places
, а для поля visited
будет использоваться случайное значение 0
или 1
.
Класс PlacesTableSeeder
будет выглядеть следующим образом после всех обновлений:
<?php
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class PlacesTableSeeder extends Seeder
{
static $places = [
'Berlin',
'Budapest',
'Cincinnati',
'Denver',
'Helsinki',
'Lisbon',
'Moscow',
'Nairobi',
'Oslo',
'Rio',
'Tokyo'
];
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
foreach (self::$places as $place) {
DB::table('places')->insert([
'name' => $place,
'visited' => rand(0,1) == 1
]);
}
}
}
Сохраните и закройте файл после внесения всех изменений.
Классы типа seeder не загружаются автоматически в приложение. Нам нужно изменить главный класс DatabaseSeeder
, чтобы добавить вызов класса типа seeder, который мы только что создали.
Откройте файл database/seeds/DatabaseSeeder.php
с помощью nano
или вашего любимого редактора:
- nano database/seeds/DatabaseSeeder.php
Класс DatabaseSeeder
выглядит стандартным образом: он наследуется от класса Seeder
и имеет метод run
. Мы обновим этот метод, чтобы включить PlacesTableSeeder
.
Обновите текущий метод run
внутри вашего класса DatabaseSeeder
, удалив закомментированную строку и заменив ее на следующий выделенный код:
…
public function run()
{
$this->call(PlacesTableSeeder::class);
}
...
Так будет выглядеть класс DatabaseSeeder
после обновления:
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
$this->call(PlacesTableSeeder::class);
}
}
Сохраните и закройте файл после внесения изменений в его содержимое.
Мы завершили настройку миграции и наполнения для нашей таблицы places
. На следующем шаге мы узнаем, как их запускать.
Перед продолжением нужно убедиться, что ваше приложение готово и запущено. Мы настроим ключ шифрования приложения и получим доступ к приложению из браузера, чтобы протестировать веб-сервер.
Чтобы сгенерировать ключ шифрования, требуемый Laravel, вы можете использовать команду artisan key:generate
:
- docker-compose exec app php artisan key:generate
После получения ключа вы сможете получить доступ к приложению, указав в браузере имя хоста сервера или IP-адрес для порта 8000
:
http://server_host_or_ip:8000
Страница будет выглядеть следующим образом:
Это означает, что приложение может подключаться к базе данных, но оно не может найти таблицу с именем places
. Теперь мы создадим таблицу places
, используя следующую команду migrate
artisan:
- docker-compose exec app php artisan migrate
Вывод будет выглядеть следующим образом:
OutputMigration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.06 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.06 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds)
Migrating: 2020_02_10_144134_create_places_table
Migrated: 2020_02_10_144134_create_places_table (0.03 seconds)
Вы увидите, что несколько других миграций было выполнено наряду с настроенной нами миграцией create_places_table
. Эти миграции генерируются автоматически, когда установлен Laravel. Хотя мы не будем использовать эти дополнительные таблицы сейчас, они будут необходимы в будущем при расширении приложения для зарегистрированных пользователей и запланированных заданий. Пока что вы можете оставить их как есть.
На данный момент наша таблица пустая. Нам нужно запустить команду db:seed
, чтобы наполнить базу данных нашими выбранными местами:
- docker-compose exec app php artisan db:seed
В результате будет запущен наш класс seeder и будут добавлены образцы значений, которые мы определили в нашем классе PlacesTableSeeder
. Вывод будет выглядеть следующим образом:
OutputSeeding: PlacesTableSeeder
Seeded: PlacesTableSeeder (0.06 seconds)
Database seeding completed successfully.
Теперь перезагрузите страницу приложения в браузере. Вы увидите приблизительно следующую страницу:
Каждый раз, когда вы захотите начать с нуля, вы можете удалить все ваши таблицы базы данных, используя следующую команду:
- docker-compose exec app php artisan db:wipe
OutputDropped all tables successfully.
Чтобы запустить миграцию приложения и заполнение таблиц с помощью одной команды, вы можете использовать следующий вариант:
- docker-compose exec app php artisan migrate --seed
OutputMigration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.06 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.07 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds)
Migrating: 2020_02_10_144134_create_places_table
Migrated: 2020_02_10_144134_create_places_table (0.03 seconds)
Seeding: PlacesTableSeeder
Seeded: PlacesTableSeeder (0.06 seconds)
Database seeding completed successfully.
Если вы захотите откатить изменения, запустите следующую команду:
- docker-compose exec app php artisan migrate:rollback
В результате будет запущен метод down
для каждого класса миграции внутри папки migrations
. Как правило, он удаляет все таблицы, созданные в классах миграции, оставляя все остальные таблицы, которые могли быть созданы вручную. Вывод будет выглядеть следующим образом:
OutputRolling back: 2020_02_10_144134_create_places_table
Rolled back: 2020_02_10_144134_create_places_table (0.02 seconds)
Rolling back: 2019_08_19_000000_create_failed_jobs_table
Rolled back: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds)
Rolling back: 2014_10_12_100000_create_password_resets_table
Rolled back: 2014_10_12_100000_create_password_resets_table (0.02 seconds)
Rolling back: 2014_10_12_000000_create_users_table
Rolled back: 2014_10_12_000000_create_users_table (0.02 seconds)
Команда отката изменений особенно полезна, когда вы вносите изменения в модели приложения, а команда db:wipe
не может использоваться, например, если несколько систем используют одну базу данных.
В этом руководстве мы увидели, как использовать миграции и наполнения для облегчения настройки баз данных для разработки и тестирования приложения Laravel 6.
В качестве следующего шага вы можете ознакомиться с документацией Laravel для получения более подробной информации о том, как использовать конструктор запросов, и о том, как использовать модели Eloquent для дальнейшей абстракции схемы базы данных вашего приложения.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!