Миграции
Часто в процессе работы над сайтом приходится вносить изменения в структуру базы данных. Заказчики добавляют много "хотелок" в процессе осознания каким они хотят видеть свой сайт. Чтобы в дальнейшем было удобно поддерживать проект, а также подключать к работе новых программистов, удобно использовать миграции.
Они будут сохранять все изменения базы в специальных php файлах и выполнив их всегда можно получить актуальное состояние базы. В Symfony для управления миграциями используется DoctrineMigrationsBundle. Подробнее с ним можно познакомить на страницах официальной документации
1. Установка
composer require doctrine/doctrine-migrations-bundle "^2.0"
2. Настройка
После установки автоматически происходит подключение бандла в файле config/bundles.php
// config/bundles.php
return [
// ...
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
// ...
];
Настройку можно произвести в файле config/packages/doctrine_migrations.yaml, который создается автоматически.
Стандартные настройки выглядят следующим образом:
# config/packages/doctrine_migrations.yaml
doctrine_migrations:
dir_name: '%kernel.project_dir%/src/Migrations'
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
namespace: DoctrineMigrations
3. Базовое использование
Представим такую ситуацию, нам необходимо внедрить модуль новостей в наш проект. Для начала нужно создать сущность для новостей.
php bin/console make:entity
Далее мы отвечает на соответствующие вопросы и получаем в результате примерно следующее:
Add another property? Enter the property name (or press to stop adding fields):
> deleted
Field type (enter ? to see all types) [string]:
> integer
Can this field be null in the database (nullable) (yes/no) [no]:
> true
updated: src/Entity/AppBundleNews.php
Add another property? Enter the property name (or press to stop adding fields):
>
Success!
Next: When you're ready, create a migration with php bin/console make:migration
Вводим команду для создания миграции.
php bin/console doctrine:database:create
Created database `rest_api` for connection named default
MacBook-Pro-Vaceslav-4:rest-api soprantsov$ php bin/console make:migration
Success!
Next: Review the new migration "src/Migrations/Version20201004180202.php"
Then: Run the migration with php bin/console doctrine:migrations:migrate
See https://symfony.com/doc/current/bundles/DoctrineMigrationsBundle/index.html
В результате мы получили php файл миграции, который имеет следующий вид:
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20201004180202 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('CREATE TABLE app_bundle_news (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, anons LONGTEXT DEFAULT NULL, publish DATETIME DEFAULT NULL, content LONGTEXT NOT NULL, active INT DEFAULT NULL, deleted INT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('DROP TABLE app_bundle_news');
}
}
4. Запуск миграции
php bin/console doctrine:migrations:migrate
Функция up() выполняется при запуске миграции и создает таблицу в базе, а down() - при откате миграции, она удаляет таблицу новостей. Давайте протестируем их.
php bin/console doctrine:migrations:migrate
Application Migrations
WARNING! You are about to execute a database migration that could result in schema changes and data loss. Are you sure you wish to continue? (y/n)y
Migrating up to 20201004180202 from 0
++ migrating 20201004180202
-> CREATE TABLE app_bundle_news (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, anons LONGTEXT DEFAULT NULL, publish DATETIME DEFAULT NULL, content LONGTEXT NOT NULL, active INT DEFAULT NULL, deleted INT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
++ migrated (took 71.6ms, used 18M memory)
------------------------
++ finished in 75.8ms
++ used 18M memory
++ 1 migrations executed
++ 1 sql queries
5. Откат миграции
А теперь откатим изменения, для этого нужно узнать версию последней миграции, потом запустить команду:
doctrine:migrations:execute {migration version} --down
c флагом --down
php bin/console doctrine:migrations:latest
20201004180202
MacBook-Pro-Vaceslav-4:rest-api soprantsov$ php bin/console doctrine:migrations:execute 20201004180202 --down
WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)y
-- reverting 20201004180202
-> DROP TABLE app_bundle_news
-- reverted (took 25ms, used 18M memory)
6. Добавление поля
В дальнейшем нам может понадобится добавить дополнительные поля к нашим сущностям.
Добавим поле "Дата удаления" к нашим новостям.
/**
* Дата удаления
* @var $deleted_date \DateTime
* @ORM\Column (type="datetime", nullable=true)
*/
private $deleted_date;
Сгенерируем геттеры и сеттеры
php bin/console make:entity App --regenerate
Обычно для каждого проекта я использую 2 базы данных, для разработики и тестов, а также для prod режима.
php bin/console doctrine:schema:update --force
Далее необходимо создать миграцию изменений базы. Для режима dev используется команда:
php bin/console doctrine:migrations:diff -e prod
Теперь накатим миграцию на продакшн
php bin/console doctrine:migrations:migrate -e prod
На этом вроде как все, успехов в работе.