Миграции
Winter умеет создавать схему БД из атрибутов сущностей: команда db migrate
сканирует репозитории, читает #[Table] и атрибуты колонок и генерирует
CREATE TABLE, индексы и внешние ключи. Повторный запуск безопасен.
Что такое миграции и зачем
Миграция здесь — генерация DDL (структуры БД) из кода.
Проблема. Держать SQL-схему отдельно от сущностей — двойная работа: добавили
поле в класс, не забудь ALTER TABLE. Схема и код расходятся, а поднять БД с нуля
на новой машине — ручной труд.
Решение. Опишите структуру один раз атрибутами сущности (см.
Сущности), а db migrate создаст таблицы из них. Об этом
и раздел.
Это не полноценная система миграций
db migrate — forward-only генератор: создаёт то, чего нет. Он не делает
diff, DROP, изменение колонок, миграцию данных и не ведёт таблицу версий (см.
Ограничения). Обычно применяется на первом деплое и в dev; эволюцию
схемы в проде ведут отдельным инструментом.
Три условия опт-ина
Чтобы репозиторий попал в миграцию, нужны все три — иначе он молча пропускается:
- Репозиторий обнаружим — файл под
Kernel::$pathRoot(или корнем плагина). - У сущности есть
#[Table]— маркер таблицы. - У конфига есть
#[Migratable]— иначе конфиг и его репозитории не сканируются.
#[Migratable] // (3) конфиг включён в миграцию
class MainDbConfig extends DbConfig { /* ... */ }
#[Table] // (2) сущность миграбельна
class User { /* поля с атрибутами колонок */ }
class UserRepository extends Repository // (1) лежит под pathRoot
{
protected string $dbConfigClassName = MainDbConfig::class;
protected string $entityClassName = User::class;
public static string $table = 'users';
}Запуск
php call db ping # проверить подключение
php call db sql # показать сгенерированный SQL (без выполнения)
php call db migrate # выполнить миграциюdb sql — безопасный предпросмотр: печатает DDL, ничего не меняя. db migrate
выполняет. Полный набор флагов — в CLI → db.
Приоритет и расширения
Атрибуты на классе конфига:
#[Migratable(priority)]— порядок между конфигами:High→Normal→Low(меньше — раньше). Полезно, когда одни таблицы ссылаются на другие.#[Extension('name', ...)]— расширение PostgreSQL, повторяемо. Ставится какCREATE EXTENSION IF NOT EXISTSдо создания таблиц.
use Flytachi\Winter\K2\Ppa\Mapping\Attributes\Config\Migratable;
use Flytachi\Winter\K2\Ppa\Mapping\Attributes\Config\Extension;
use Flytachi\Winter\K2\Ppa\Mapping\Constants\MigratablePriority;
#[Migratable(MigratablePriority::High)] // раньше остальных
#[Extension('pgcrypto')] // для gen_random_uuid()
class AuthDbConfig extends DbConfig { /* ... */ }Порядок выполнения
Внутри одного конфига DDL эмитится в фиксированном порядке — по цепочке зависимостей:
1. EXTENSIONS (только pgsql)
2. SCHEMAS (только pgsql — CREATE SCHEMA)
3. TABLES (CREATE TABLE, включая первичные ключи)
4. INDEXES (CREATE INDEX)
5. CONSTRAINTS (ALTER TABLE ADD CONSTRAINT — FK, CHECK)Расширения первыми, потому что DEFAULT-выражения таблиц могут ссылаться на их
функции (gen_random_uuid()); схемы до таблиц; индексы и ограничения после —
они ссылаются на колонки.
Идемпотентность
Повторный db migrate безопасен: каждый оператор либо использует IF NOT EXISTS,
либо его ошибка «объект уже существует» перехватывается и помечается EXIST
(жёлтым), а не FAILED (красным). Любой другой SQLSTATE → FAILED (с текстом
ошибки при DEBUG=true).
Выбор фаз флагами
php call db migrate # все фазы (по умолчанию -e -s -t -i -c)
php call db migrate -t -i # только таблицы + индексы
php call db migrate -e # только расширения (pgsql)Ограничения
Границы инструмента, чтобы не было сюрпризов в проде:
- Нет diff / drift-детекции — только создаёт отсутствующее, не замечает изменённых/удалённых колонок.
- Нет
DROP— ни таблиц, ни колонок, ни ограничений. - Нет транзакций — операторы выполняются независимо.
- Нет миграции данных — только DDL, сидинг отдельно.
- Нет таблицы версий — каждый запуск прогоняет все операторы (идемпотентно).
Для эволюции схемы в проде используйте выделенный инструмент (Phinx, Liquibase),
оставив соответствующие сущности без #[Table] (или конфиг без #[Migratable]).
Дальше
- Сущности — полный каталог атрибутов колонок
- CLI → db — команда
dbи все флаги - Подключение —
#[Migratable]и#[Extension]на конфиге