Open-source project
cakephp/phinx avatar
cakephp/phinx

cakephp/phinx: PHP database migrations without an ORM

PHP Database Migrations for Everyone

4,539 stars884 forksPHPMIT

At a glance

What is it?
Phinx is a standalone migration tool for PHP that runs against MySQL, PostgreSQL, SQLite and Microsoft SQL Server. It is a small CLI, not a framework, and the trade-offs follow from that choice.
Who is it for?
Adopt Phinx if you write PHP and want migrations that do not drag an ORM or a framework along with them, and if you are willing to keep migrations as plain versioned files. Do not adopt it if you rely on PostgreSQL unique constraints on a table, which the README lists as a known limitation, or if you expect the tool to manage schema discovery for you.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 70 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Phinx replaces in a PHP project

Most PHP applications that need schema changes end up with one of two arrangements. Either the framework owns migrations, and you cannot use them without the framework, or somebody keeps a numbered folder of .sql files and a note in the deploy script about which ones have run. Phinx targets the second group. The README describes it as "just about migrations without all the bloat of a database ORM system or framework", which is an accurate summary of the scope: it connects to a database, tracks which migration files have executed, and runs the rest.

The intended user is a PHP developer who already has a database and a deployment process, and who wants schema changes to be versioned alongside the code so that branches and rollbacks behave predictably. The README lists branching as a feature, and that is the real argument. If a feature branch adds a column, the migration file travels with the branch. Merging the branch merges the migration. Nothing about that requires an ORM, and nothing about it requires the rest of a framework either.

It is worth being clear about what it is not. Phinx does not model your tables as objects, does not generate queries for your application, and does not read your existing schema to infer anything. It executes the migrations you write and records the result. That narrowness is the point.

How the migration runner actually works

A Phinx project has a configuration file and a migrations directory. The configuration names the database adapter, the host, the database name, credentials, and the directory where migration files live. Each migration is a PHP class extending the base migration class, with an up method and a down method. The up method describes the change forward, the down method reverses it.

The migration classes use a database-agnostic API rather than raw SQL, which is what lets the same file run against MySQL, PostgreSQL, SQLite and Microsoft SQL Server. The README lists those four as natively supported adapters. That abstraction is also the source of the tool's sharpest limitation, described below.

When you run the migrate command, Phinx reads the migrations directory, compares the version identifiers in the filenames against the versions recorded in a tracking table in your database, and executes the ones that are missing, in order. The rollback command walks that record backwards and calls the down methods. Because the state lives in the database rather than in a local file, two developers running against the same database see the same picture, and a deployment step can check whether anything is pending before it proceeds. The README lists migrating on deployment and seeding data after database creation as separate features, which suggests the intended flow: create the schema, then load reference data through seed classes.

Installing Phinx and running a first migration

The README gives Composer as the fastest route. The package name is robmorgan/phinx, which is worth noting because the repository lives under the cakephp organisation while the Composer package kept its original name. Requiring it adds the dependency to your project's composer.json.

bash
curl -sS https://getcomposer.org/installer | php
php composer.phar require robmorgan/phinx
php composer.phar install
php vendor/bin/phinx

Running the binary with no arguments prints the available commands. The README states that Phinx requires PHP 8.1 or later, so check your runtime before adding it to an older project.

The README does not walk through initialising a project or creating a migration file, so what follows is the shape of the workflow rather than a quoted example. You create a configuration file that names your database connection and your migrations directory, then add migration classes with up and down methods and apply them with the migrate command. Running status afterwards should list the migration as applied; if it does not, the connection details in the configuration are the first thing to check. The README points to phinx.org for the full command reference, and that is where the exact options for each command are documented.

The PostgreSQL unique constraint gap

The README has a Limitations section with exactly one entry, and it is specific: on PostgreSQL, Phinx is not able to set a unique constraint on a table. The linked issue is number 1026. That is a narrow gap but an awkward one, because unique constraints are common in real schemas and PostgreSQL is a common production database for PHP applications.

What this means in practice is that a migration written with the portable API cannot express that constraint on PostgreSQL, and you need a different route for that particular change. The README does not document a workaround, and it does not say whether the limitation applies to unique indexes as well as unique constraints. Anyone whose schema depends on unique constraints should treat this as the deciding factor and verify the current behaviour against their own PostgreSQL version before planning around it.

The broader trade-off is the database-agnostic API itself. Writing migrations against an abstraction means you get portability across the four supported adapters, and you also get the lowest common denominator of what those four can express. When you need something adapter-specific, you are working outside the API that makes Phinx worth using. That is not a defect, but it does mean Phinx fits projects that treat the database as a portable dependency better than projects that treat it as a tuned, vendor-specific component.

Phinx compared with Doctrine Migrations

The obvious alternative in PHP is Doctrine Migrations, and the difference is architectural rather than cosmetic. Doctrine Migrations is part of the Doctrine project and is designed to sit alongside the Doctrine ORM. It can compare your entity mappings against the live database and generate migration files from the difference, which means the schema definition lives in your PHP entity classes and migrations are partly derived from them.

Phinx has no equivalent. There is no mapping layer to diff against, so every migration is written by hand. You decide what the up and down methods do. That is more typing and more room for a mistake in the down method, and it also means the migration file is the only description of the change. There is no second source of truth that can drift.

Which one to pick depends on whether you already use the Doctrine ORM. If you do, the generated migrations are a real time saving and the integration is already there. If you do not, pulling in Doctrine's mapping layer to get migrations is a large dependency for a small need, and Phinx is the narrower tool. The README's framing, that Phinx is migrations "without all the bloat of a database ORM system or framework", is a fair statement of the same distinction from the other side.

Maintenance, release cadence and the MIT licence

The repository is not archived. The most recent release listed is 0.16.12, dated 2026-07-03, and the last push to the repository was on 2026-07-21. The release before that, 0.16.11, is dated 2026-03-15, and 0.16.10 is dated 2025-07-08. The gaps between those three releases are roughly five months and roughly eight months, so the cadence is irregular rather than weekly. That is a normal pattern for a mature tool whose surface area is stable, but it does mean you should not expect a fix for a newly found edge case to land in days.

Upgrade cost is low by design. The package is a CLI and a set of migration base classes, and the migrations you write are your own files. Moving from one 0.16.x patch release to the next should not require rewriting migrations. The README points to a version and branch overview wiki page for branch and PHP compatibility, which is the page to read before a major version jump, since the minimum PHP version is already 8.1.

The licence is MIT, stated in the README with the copyright line "Copyright (c) 2017 Rob Morgan". MIT permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. If you vendor Phinx or ship it inside a distributed application, keep the licence text with it. That is a description of what the licence says, not legal advice; check with your own counsel if the distribution model is unusual.

Editorial conclusion

Adopt Phinx if you write PHP and want migrations that do not drag an ORM or a framework along with them, and if you are willing to keep migrations as plain versioned files. Do not adopt it if you rely on PostgreSQL unique constraints on a table, which the README lists as a known limitation, or if you expect the tool to manage schema discovery for you. Before committing, run php vendor/bin/phinx in a scratch project to see the available commands, and confirm your runtime is PHP 8.1 or later, since that is the minimum the README states.

Frequently asked questions

What is Phinx?

Phinx is a standalone database migration tool for PHP, distributed as the Composer package robmorgan/phinx. It manages schema changes through versioned PHP migration files with up and down methods, and it natively supports MySQL, PostgreSQL, SQLite and Microsoft SQL Server.

Is Phinx actively maintained?

The repository is not archived, the latest listed release is 0.16.12 from 2026-07-03, and the last push was on 2026-07-21. Release spacing across 0.16.10, 0.16.11 and 0.16.12 is irregular, so treat it as a stable project rather than a fast-moving one.

How do I use Phinx in a PHP project?

Install it with Composer as robmorgan/phinx, then run php vendor/bin/phinx to see the available commands. The README points to phinx.org for the comprehensive documentation covering the migration workflow.

Official sources

  1. cakephp/phinx on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cakephp-phinx.svg)](https://hysenlabs.com/projects/cakephp-phinx)