{"id":15024883,"url":"https://github.com/mvrhov/migratum","last_synced_at":"2026-02-22T04:30:50.879Z","repository":{"id":57022383,"uuid":"119395329","full_name":"mvrhov/migratum","owner":"mvrhov","description":"Sane database migrations","archived":false,"fork":false,"pushed_at":"2018-02-01T07:50:46.000Z","size":31,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-14T18:38:54.214Z","etag":null,"topics":["database","ddl","migrations","postgres","postgresql"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mvrhov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-29T14:44:16.000Z","updated_at":"2018-12-21T17:04:09.000Z","dependencies_parsed_at":"2022-08-23T13:50:53.421Z","dependency_job_id":null,"html_url":"https://github.com/mvrhov/migratum","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mvrhov/migratum","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvrhov%2Fmigratum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvrhov%2Fmigratum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvrhov%2Fmigratum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvrhov%2Fmigratum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mvrhov","download_url":"https://codeload.github.com/mvrhov/migratum/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvrhov%2Fmigratum/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29704783,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-22T03:17:42.375Z","status":"ssl_error","status_checked_at":"2026-02-22T03:17:31.622Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","ddl","migrations","postgres","postgresql"],"created_at":"2024-09-24T20:01:07.349Z","updated_at":"2026-02-22T04:30:50.847Z","avatar_url":"https://github.com/mvrhov.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Migratum: Templated Database Migrations\n\n### Intro\nMost of the PHP migration tools force you to write the migrations in PHP with classes and function, \nYou are database agnostic then, but on the other hand you are usually limited to the lowest \ncommon denominator of what's supported by databases in features you can use.\nWith Migratum you write migrations directly in database specific DDL. \nOn top of that you can pass some context into each migration.\n\nMost people think that having the migrations in DB specific DDL doesn't allow you to change the database\nbut let's be honest here. Almost nobody changes the database after it has been decided on the platform.\n\n\n### Features\n\n* utilize any DDL \u0026 DML functionality your database provides\n* pass parameters/context to your migrations\n* create migrations for multiple database providers e.g MySQL and PostgreSQL\n* migrate up and down\n* migrate pending up migrations\n* migrations in multiple directories and/or namespaces\n* multiple environments \n* uses twig to \n\n### Supported Adapters\nMigratum natively supports following database platforms:\n\n* PostgreSQL\n\n### Install \u0026 Run\n\n1. Install Composer:\n\n    ```\n    curl -sS https://getcomposer.org/installer | php\n    ```\n\n1. Require Migratum as a dependency using Composer:\n\n    ```\n    php composer.phar require mvrhov/migratum\n    ```\n\n1. Execute Migratum:\n\n    ```\n    php composer.phar install\n    ```\n\n### Commands\n\nAll commands have a dry-run mode where you can se what's going to be run. If you also provide `-v` you can also see the queries that are going to be executed.\n\n#### migratum:init\nInitializes migratum, by creating default configuration file\n\n#### migratum:create\nCreate empty migration in some namespace\n\n`bin/migratum migratum:create \"create table account\"` creates an empty migration in default namespace `\u003ccurrent_timestamp\u003e_create_table_account`\n\n`bin/migratum migratum:create \"create table foo\" -s foo.1` creates an empty migration in namespace `foo` named `\u003ccurrent_timestamp\u003e_create_table_foo`\n\n#### migratum:migrate\n\n`bin/migratum migratum:migrate` apply all pending migrations in order regardless the namespace they come from\n\n`bin/migratum migratum:migrate -t \u003ctimestamp\u003e` apply all pending migrations up to `\u003ctimestamp\u003e` in order regardless the namespace they come from\n\n\n#### migratum:pending\nSometimes when multiple people work on a project it happens that there are some migrations that other people have created\nand those migrations sit in between yours.\nWhen this happens you should review those migrations and if they don't conflict with yours, then you should run the pending \ncommand. If they do conflict, then unfortunately the only way to do proper migrations is to rollback back up to that \nmigration, fix your migrations and apply them again.\n\n#### migratum:rollback\nRevert some of the applied migrations \n\n`bin/migratum migratum:rollback -b \u003ccount\u003e` rollback applied migrations up to `\u003ccount\u003e` migrations regardless of version\n\n`bin/migratum migratum:rollback -t \u003ctimestamp\u003e` rollback applied migrations up to `\u003ctimestamp\u003e` migrations\n\n#### migratum:status\nThe status command will report the current state of the database.\n\n### Migration example\n\n* timestamps.sql.twig\n```jinja\n{% macro timestamp_triggers(tableName) %}\nDROP TRIGGER IF EXISTS set_updated_at_{{ tableName }} ON {{ tableName }};\n\nCREATE TRIGGER set_updated_at_{{ tableName }}\nBEFORE UPDATE ON {{ tableName }} FOR EACH ROW\nEXECUTE PROCEDURE set_updated_at_column();\n\n{% endmacro timestamp_triggers %}\n\n{% macro drop_timestamp_triggers(tableName) %}\nDROP TRIGGER IF EXISTS set_updated_at_{{ tableName }} ON {{ tableName }};\n{% endmacro drop_timestamp_triggers %}\n```\n\n* 20180110851900_create_default_triggers.sql.twig\n```jinja\n{% block up %}\n-- @Migratum\\QueryBlockStart\nCREATE OR REPLACE FUNCTION set_updated_at_column() RETURNS TRIGGER AS $$\nBEGIN\n   NEW.updated_at = now();\n   RETURN NEW;\nEND;\n$$ language 'plpgsql';\n{% endblock up %}\n\n{% block down %}\nDROP FUNCTION set_updated_at_column;\n{% endblock down %}\n```\n\n* 20180111115900_create_account.sql.twig\n```jinja\n{% block up %}\n{% import 'timestamps.sql.twig' as t %}\n\n{% set table = 'account' %}\n\nCREATE TABLE {{ table }} (\n    id_{{ table }} INTEGER GENERATED BY DEFAULT AS IDENTITY,\n    name varchar(200) NOT NULL,\n    email varchar(200) NOT NULL,\n    enabled boolean NOT NULL,\n    created_at timestamp DEFAULT now() NOT NULL,\n    updated_at timestamp,\n\n    PRIMARY KEY(id_{{ table }})\n);\n\n{{ t.timestamp_triggers(table) }}\n{% endblock up %}\n\n{% block down %}\n{% set table = 'account' %}\n\n{{ t.drop_timestamp_triggers(table) }}\n\nDROP TABLE {{ table }};\n{% endblock down %}\n```\n\n### Gotchas\n\nIf you look closely, the migrations above you can see that there is a specific SQL comment present in create triggers migration\nThis comment is needed because the Migratum breaks the migration per SQL statement based on `;` character.\nThis becomes a problem when one has stored procedures/triggers... that are basically a group of multiple SQL sentences \nor said stored procedure/trigger... utilizes the language where the ; is also end of statement. \nAs there is too many different dialects of this you must mark the unbreakable parts with `-- @Migratum\\QueryBlockStart`.\nYou can repeat the `-- @Migratum\\QueryBlockStart` as may times as you need inside a migration and each of them  \nstarts new non breakable statement. \nIf you want to exit non breakable statement mode you should add the following SQL comment `-- @Migratum\\QueryBlockEnd`.\n\n \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmvrhov%2Fmigratum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmvrhov%2Fmigratum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmvrhov%2Fmigratum/lists"}