PHPackages                             dbschemix/migrator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. dbschemix/migrator

ActiveLibrary[Database &amp; ORM](/categories/database)

dbschemix/migrator
==================

dbschemix: database migration

1.1.0(1w ago)13MITPHPPHP ^8.3

Since May 15Pushed 1w agoCompare

[ Source](https://github.com/dbschemix/migrator)[ Packagist](https://packagist.org/packages/dbschemix/migrator)[ RSS](/packages/dbschemix-migrator/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (3)Dependencies (12)Versions (5)Used By (0)

Database Migrator
=================

[](#database-migrator)

Консольная программа для управления миграциями.

Консольная утилита на основе:

-
-
-

### Command

[](#command)

- **init** — инициализация проекта: создание папки для миграций и конфигурационного файла.
- **up** — применение всех ожидающих миграций до самой свежей.
- **down** — откат последней примененной миграции (или нескольких).
- **fixture** — применение всех фикстур.
- **create** — создание файла миграции (удобно при разработке).
- **verify** — последовательный запуск up и сразу down для последней версии миграций (удобно при разработке).
- **redo** — последовательный запуск down и сразу up для последней миграции (удобно при разработке).

### setup

[](#setup)

Например, для базы данных с именем *main* под управлением сервера **postgres**:

```
mkdir -p ./migration/pgsql/{main,main-fixture}
```

Описываем конфигурацию:

```
$migrator = new Migrator(
    list: [
        new Migration(
            path: __DIR__ . '/migration/postgres/main',
            driver: new PdoDriver(
                dsn: 'pgsql:host=postgres;port=5432;dbname=main',
                username: 'postgres',
                password: 'postgres',
            )
        )
    ],
);
```

### migration

[](#migration)

Команды миграции описываются на языке SQL, например:

```
-- @up
CREATE TABLE IF NOT EXISTS public.entity (
    id serial NOT NULL,
    parent_id integer NOT NULL,
    created_at timestamp(0) DEFAULT CURRENT_TIMESTAMP NOT NULL,
    updated_at timestamp(0) DEFAULT CURRENT_TIMESTAMP NOT NULL,
    CONSTRAINT entity_pkey PRIMARY KEY (id)
);
CREATE INDEX IF NOT EXISTS "I_entity_parent_id" ON public.entity USING btree (parent_id);

-- @down
DROP INDEX IF EXISTS I_entity_parent_id;
DROP TABLE IF EXISTS public.entity;
```

Управляющие команды:

- `@up`
- `@down`
- `@skip`

Если команды не указаны, то весь код будет вычитан как секция `up`.
Если нужно скипнуть файл целиком, то можно добавить в название постфикс `skip`, например `202501011025_name_skip.sql`

### CLI application

[](#cli-application)

```
use dbschemix\pdo\Driver;
use dbschemix\core\Migration;
use dbschemix\core\Migrator;
use dbschemix\migrator\cmd\Console;
use dbschemix\migrator\tools\PrettyConsoleOutput;

require dirname(__DIR__) . '/vendor/autoload.php';

$migrator = new Migrator(
    list: [
        new Migration(
            path: __DIR__ . '/migration/sqlite/memory',
            driver: new Driver(
                dsn: 'sqlite:' . __DIR__ . '/data/sqlite/db.sqlite3',
            )
        ),
    ],
    eventSubscribers: [
        new PrettyConsoleOutput(),
    ],
);

Console::run($migrator);
```

### Example

[](#example)

```
make app
```

```
/example $ php cli.php migrate:init
[sqlite/db] initialization: setup.sql done

/example $ php cli.php migrate:up
[sqlite/db] up: 202501011024_entity_create.sql done
[sqlite/db] up: 202501021024_account_create.sql done
[sqlite/db] up: 202501021025_account_email.sql done

/example $ php cli.php migrate:down
[sqlite/db] down: 202501021025_account_email.sql done
[sqlite/db] down: 202501021024_account_create.sql done
[sqlite/db] down: 202501011024_entity_create.sql done
```

#### With exactly all

[](#with-exactly-all)

If any migration fails, the entire batch is rolled back, leaving the database unchanged.

```
/example $ php cli.php migrate:up --exactly-all
[sqlite/db] up: 202501011024_entity_create.sql done
[sqlite/db] up: 202501021024_account_create.sql done
[sqlite/db] up: 202501021025_account_email.sql done
```

#### With repeatable

[](#with-repeatable)

```
/example $ php cli.php migrate:up --with-repeatable
[sqlite/db] up: 202501011024_entity_create.sql done
[sqlite/db] up: 202501021024_account_create.sql done
[sqlite/db] up: 202501021025_account_email.sql done
[sqlite/db] repeatable: 202501011024_entity_correction.sql done
[sqlite/db] repeatable: 202501011024_entity_correction_2.sql done
```

#### Down with latest version

[](#down-with-latest-version)

```
/example $ php cli.php migrate:up --limit=1
[sqlite/db] up: 202501011024_entity_create.sql, vers: 1772723563954 done

/example $ php cli.php migrate:up --limit=2
[sqlite/db] up: 202501021024_account_create.sql, vers: 1772723566084 done
[sqlite/db] up: 202501021025_account_email.sql, vers: 1772723566084 done

/example $ php cli.php migrate:down --latest-version
[sqlite/db] down: 202501021025_account_email.sql, vers: 1772723566084 done
[sqlite/db] down: 202501021024_account_create.sql, vers: 1772723566084 done
```

#### Redo with latest version

[](#redo-with-latest-version)

```
/example $ php cli.php migrate:up
[sqlite/db] up: 202501021024_account_create.sql, vers: 1772723718828 done
[sqlite/db] up: 202501021025_account_email.sql, vers: 1772723718828 done

/example $ php cli.php migrate:redo --latest-version
[sqlite/db] down: 202501021025_account_email.sql, vers: 1772723718828 done
[sqlite/db] down: 202501021024_account_create.sql, vers: 1772723718828 done
[sqlite/db] up: 202501021024_account_create.sql, vers: 1772723727397 done
[sqlite/db] up: 202501021025_account_email.sql, vers: 1772723727397 done
```

#### Verify

[](#verify)

```
/example $ php cli.php migrate:create test --db=sqlite/db
/example $ php cli.php migrate:create test2 --db=sqlite/db
/example $ php cli.php migrate:create test3 --db=sqlite/db

/example $ php cli.php migrate:verify
[sqlite/db] up: 202603070850_test.sql, vers: 177287432696 done
[sqlite/db] up: 202603070850_test2.sql, vers: 177287432696 done
[sqlite/db] up: 202603070850_test3.sql, vers: 177287432696 done
[sqlite/db] down: 202603070850_test3.sql, vers: 177287432696 done
[sqlite/db] down: 202603070850_test2.sql, vers: 177287432696 done
[sqlite/db] down: 202603070850_test.sql, vers: 177287432696 done
```

**With limit**

```
/example $ php cli.php migrate:verify --limit=1
[sqlite/db] up: 202603070850_test.sql, vers: 177287441498 done
[sqlite/db] down: 202603070850_test.sql, vers: 177287441498 done
```

**error**

```
/example $ php cli.php migrate:verify
[sqlite/db] up: 202603070850_test.sql, vers: 177287479980 done
[sqlite/db] up: 202603070850_test2.sql error
SQLSTATE[HY000]: General error: 1 incomplete input
-- SQL CODE
INSERT INTO ededede

[sqlite/db] down: 202603070850_test.sql, vers: 177287479980 done
202603070850_test2.sql: SQLSTATE[HY000]: General error: 1 incomplete input
```

### Docker / docker-compose

[](#docker--docker-compose)

The library ships a thin runtime image. The image contains PHP, the `pdo_mysql` / `pdo_pgsql` / `pdo_sqlite` extensions and an entrypoint — it does **not** contain the library. The library and your custom code (e.g. `eventSubscribers`) come from your project's mounted `vendor/`.

**Config contract.** Provide a PHP file that returns the `Migrator`:

```
