A small, dependency-light database migration library for PHP. It discovers your
migration classes on disk, keeps a version table in sync, and runs the
up()/down() side of each migration either programmatically or through a
simple command-line interface.
- Plain PDO under the hood — works with MySQL/MariaDB, SQLite and PostgreSQL.
- A tracked version table so each migration is applied (or reverted) exactly once.
- Idempotent
up/downwith an optionalforceto re-run. - A small CLI (
init,create,status,up,down) built on InitPHP Console. - Fully typed, PSR-12 compliant, analysed with PHPStan and covered by tests.
- PHP 8.1 or higher
ext-pdoand the PDO driver for your database (pdo_mysql,pdo_sqliteorpdo_pgsql)ext-json- initphp/console
^2.1(installed automatically)
composer require initphp/barbarianA migration extends InitPHP\Barbarian\MigrationAbstract and implements up()
and down(). Each method receives a QueryInterface to run statements with and
returns a bool: returning false (or throwing) tells the runner not to
record the state change, so the migration can be retried.
By convention, files are named Migration_<timestamp>.php and the class name
matches the file name.
<?php
declare(strict_types=1);
namespace App\Migrations;
use InitPHP\Barbarian\MigrationAbstract;
use InitPHP\Barbarian\QueryInterface;
final class Migration_20240101000000 extends MigrationAbstract
{
public function up(QueryInterface $query): bool
{
$query->query('CREATE TABLE IF NOT EXISTS `users` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`email` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;');
return true;
}
public function down(QueryInterface $query): bool
{
$query->query('DROP TABLE IF EXISTS `users`');
return true;
}
}require 'vendor/autoload.php';
use InitPHP\Barbarian\Migrations;
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'root', '');
$migrations = new Migrations($pdo, __DIR__ . '/migrations', [
'migrationTable' => 'migrations_versions',
'namespace' => 'App\\Migrations', // use null for the global namespace
]);
// Apply (up) a single migration:
$migrations->upMigration(new \App\Migrations\Migration_20240101000000());
// Revert (down) a single migration:
$migrations->downMigration(new \App\Migrations\Migration_20240101000000());
// Or iterate over every discovered migration:
foreach ($migrations->getMigrations() as $version => $class) {
$migrations->upMigration(new $class());
}upMigration() and downMigration() accept a second bool $force argument to
re-run a migration that has already been applied/reverted. Problems found while
scanning the folder are available via getErrors().
First create a barbarian.json configuration file in your project root:
vendor/bin/barbarian initThis writes a template you then edit:
{
"dsn": "mysql:host=localhost;dbname=test;charset=utf8mb4",
"username": "root",
"password": "",
"folder": "/path/to/migrations/",
"table_name": "migrations_versions",
"namespace": "App\\Migrations"
}| Key | Required | Description |
|---|---|---|
dsn |
yes | PDO connection string. |
username |
yes | Database user. |
password |
yes | Database password (may be empty). |
folder |
yes | Directory containing the Migration_*.php files. |
table_name |
no | Version table name (default migrations_versions). |
namespace |
no | Namespace the migration classes live under, or null if global. |
Then:
# Create a new, empty migration in the configured folder (no database needed):
vendor/bin/barbarian create
# Show the status (up / down / pending) of every migration:
vendor/bin/barbarian status
# Apply every migration (ascending order):
vendor/bin/barbarian up
# Apply a single migration (timestamp or full class name):
vendor/bin/barbarian up --version=20240101000000
vendor/bin/barbarian up --version=Migration_20240101000000
# Revert every migration (reverse order):
vendor/bin/barbarian down
# Revert a single migration:
vendor/bin/barbarian down --version=20240101000000Every command accepts --config=/path/to/barbarian.json to point at a specific
configuration file (it defaults to ./barbarian.json).
The version table DDL is generated per driver (mysql, sqlite, pgsql); any
other driver falls back to the MySQL grammar. The migration statements you write
in up()/down() are, of course, your own responsibility to keep portable.
In-depth guides with examples live in the docs/ directory:
- Installation
- Configuration
- Writing migrations
- Command-line usage
- Programmatic usage
- Database drivers
- Extending Barbarian
composer install
composer test # run the PHPUnit suite
composer cs # check coding standards (PSR-12)
composer stan # run static analysis (PHPStan)
composer qa # all of the aboveReleased under the MIT License.