Skip to content

Commit 79f7554

Browse files
Add unified cake_migrations table support with BC autodetect (#965)
* Add unified cake_migrations table support with BC autodetect This change introduces a consolidated migration tracking approach for v5.0: **New Features:** - `cake_migrations` table: Single table with `plugin` column to track all migrations - `UnifiedMigrationsTableStorage`: New storage class for unified table operations - `migrations upgrade` command: Migrates data from legacy phinxlog tables **Backward Compatibility:** - Autodetect mode (default): If any `phinxlog` or `*_phinxlog` table exists, legacy mode is used automatically - no breaking changes on upgrade - Fresh installations automatically use the new `cake_migrations` table **Configuration:** - `Migrations.legacyTables = null` (default): Autodetect - `Migrations.legacyTables = false`: Force unified table - `Migrations.legacyTables = true`: Force legacy phinxlog tables **Upgrade workflow:** 1. Upgrade to v5.0 (existing apps continue working with phinxlog) 2. Run `bin/cake migrations upgrade` to migrate data 3. Set `Migrations.legacyTables = false` in config 4. Application now uses unified `cake_migrations` table Refs #822 - Address PR feedback for unified migrations table - Simplify NULL handling using 'plugin IS' => $this->plugin pattern - Remove cache complexity from UtilTrait - Replace empty() with explicit === [] check - Simplify upgradeTable() to no-op for new table format - Use in_array for phinxlog detection (simpler than loop) - Use hasTable() for phinxlog detection. Uses the new hasTable() method from CakePHP 5.3 as suggested in the PR feedback. - Add CI matrix, tests, docs for unified migrations table - Add LEGACY_TABLES CI matrix option to test both modes - Use schemaDialect()->hasTable() for phinxlog detection - Add documentation for unified table upgrade process - Add basic test for UnifiedMigrationsTableStorage - Update bootstrap to read LEGACY_TABLES from environment - Remove development notes - Hide upgrade command when legacyTables is false. When `Migrations.legacyTables` is set to `false`, the upgrade command is not needed since the user has already opted into the unified table. Only show it when in autodetect mode (null) or legacy mode (true). - Remove LEGACY_TABLES CI matrix, partial test fixes. The unified table feature works, but tests have extensive hardcoded phinxlog assumptions (99 failures). Removing CI matrix for now. - Partial fixes to BakeMigrationDiffCommandTest to show the pattern: - Add UtilTrait to get correct schema table name - Update table cleanup to include both table types - Update queries to use dynamic table name - Update tests to support unified migrations table mode - Add helper methods to TestCase for migration table operations: - getMigrationsTableName() - gets correct table name based on mode - clearMigrationRecords() - clears records with plugin filtering - getMigrationRecordCount() - counts records with plugin filtering - insertMigrationRecord() - inserts with correct structure - isUsingUnifiedTable() - checks current mode - Update command tests to use new helper methods: - MigrateCommandTest - RollbackCommandTest - StatusCommandTest - MarkMigratedTest - DumpCommandTest - BakeMigrationDiffCommandTest - Add cleanup for both phinxlog and cake_migrations tables - Re-add LEGACY_TABLES=false CI matrix option - Fix test suite for LEGACY_TABLES=false CI build - Update Util::tableName() to return cake_migrations when unified table mode is enabled - Update Manager::cleanupMissingMigrations() to use correct table name and filter by plugin - Skip cake_migrations table in bake snapshot/diff commands (like phinxlog tables) - Update TableFinder to skip cake_migrations table - Update Migrator to not drop cake_migrations during table cleanup - Update tests to use helper methods for migration record operations - Add mode-aware assertions in adapter tests - Skip some Migrator tests in unified mode that test legacy-specific behavior - Feedback and fixes. I thought the conditional logic in Manager, and unwrapping decorators pointed to a missing abstraction method. Since we're in a major anyways, I could extend the interface and have better layering as well. - Add more tests. - Fix diff baking tests to delete migration file after running migrate. The checkSync() method compares the last migration file version against the last migrated version. After the test deletes the migration record from the phinxlog table, the migration file still exists, causing checkSync() to fail because it sees an unmigrated file. The fix deletes the migration file after running migrate and before baking the diff, so checkSync() passes correctly. - Remove file. - Auto create folder. ensures a more stable setup. --------- Co-authored-by: Mark Story <mark@mark-story.com>
1 parent 7bdc30e commit 79f7554

33 files changed

+1550
-170
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ jobs:
2424
php-version: ['8.2', '8.5']
2525
db-type: [mariadb, mysql, pgsql, sqlite]
2626
prefer-lowest: ['']
27+
legacy-tables: ['']
2728
include:
2829
- php-version: '8.2'
2930
db-type: 'sqlite'
@@ -32,6 +33,10 @@ jobs:
3233
db-type: 'mysql'
3334
- php-version: '8.3'
3435
db-type: 'pgsql'
36+
# Test unified cake_migrations table (non-legacy mode)
37+
- php-version: '8.3'
38+
db-type: 'mysql'
39+
legacy-tables: 'false'
3540
services:
3641
postgres:
3742
image: postgres
@@ -135,6 +140,9 @@ jobs:
135140
export DB_URL='postgres://postgres:pg-password@127.0.0.1/cakephp_test'
136141
export DB_URL_SNAPSHOT='postgres://postgres:pg-password@127.0.0.1/cakephp_snapshot'
137142
fi
143+
if [[ -n '${{ matrix.legacy-tables }}' ]]; then
144+
export LEGACY_TABLES='${{ matrix.legacy-tables }}'
145+
fi
138146
if [[ ${{ matrix.php-version }} == '8.1' && ${{ matrix.db-type }} == 'mysql' ]]; then
139147
vendor/bin/phpunit --coverage-clover=coverage.xml
140148
else

docs/en/upgrading-to-builtin-backend.rst

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,95 @@ Similar changes are for fetching a single row::
102102
$stmt = $this->getAdapter()->query('SELECT * FROM articles');
103103
$rows = $stmt->fetch('assoc');
104104

105+
Unified Migrations Table
106+
========================
107+
108+
As of migrations 5.x, there is a new unified ``cake_migrations`` table that
109+
replaces the legacy ``phinxlog`` tables. This provides several benefits:
110+
111+
- **Single table for all migrations**: Instead of separate ``phinxlog`` (app)
112+
and ``{plugin}_phinxlog`` (plugins) tables, all migrations are tracked in
113+
one ``cake_migrations`` table with a ``plugin`` column.
114+
- **Simpler database schema**: Fewer migration tracking tables to manage.
115+
- **Better plugin support**: Plugin migrations are properly namespaced.
116+
117+
Backward Compatibility
118+
----------------------
119+
120+
For existing applications with ``phinxlog`` tables:
121+
122+
- **Automatic detection**: If any ``phinxlog`` table exists, migrations will
123+
continue using the legacy tables automatically.
124+
- **No forced migration**: Existing applications don't need to change anything.
125+
- **Opt-in upgrade**: You can migrate to the new table when you're ready.
126+
127+
Configuration
128+
-------------
129+
130+
The ``Migrations.legacyTables`` configuration option controls the behavior:
131+
132+
.. code-block:: php
133+
134+
// config/app.php or config/app_local.php
135+
'Migrations' => [
136+
// null (default): Autodetect - use legacy if phinxlog tables exist
137+
// false: Force use of new cake_migrations table
138+
// true: Force use of legacy phinxlog tables
139+
'legacyTables' => null,
140+
],
141+
142+
Upgrading to the Unified Table
143+
------------------------------
144+
145+
To migrate from ``phinxlog`` tables to the new ``cake_migrations`` table:
146+
147+
1. **Preview the upgrade** (dry run):
148+
149+
.. code-block:: bash
150+
151+
bin/cake migrations upgrade --dry-run
152+
153+
2. **Run the upgrade**:
154+
155+
.. code-block:: bash
156+
157+
bin/cake migrations upgrade
158+
159+
3. **Update your configuration**:
160+
161+
.. code-block:: php
162+
163+
// config/app.php
164+
'Migrations' => [
165+
'legacyTables' => false,
166+
],
167+
168+
4. **Optionally drop phinx tables**: Your migration history is preserved
169+
by default. Use ``--drop-tables`` to drop the ``phinxlog``tables after
170+
verifying your migrations run correctly.
171+
172+
.. code-block:: bash
173+
174+
bin/cake migrations upgrade --drop-tables
175+
176+
Rolling Back
177+
------------
178+
179+
If you need to revert to phinx tables after upgrading:
180+
181+
1. Set ``'legacyTables' => true`` in your configuration.
182+
183+
.. warning::
184+
185+
You cannot rollback after running ``upgrade --drop-tables``.
186+
187+
188+
New Installations
189+
-----------------
190+
191+
For new applications without any existing ``phinxlog`` tables, the unified
192+
``cake_migrations`` table is used automatically. No configuration is needed.
193+
105194
Problems with the builtin backend?
106195
==================================
107196

src/Command/BakeMigrationDiffCommand.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,9 @@ protected function getCurrentSchema(): array
584584
if (preg_match('/^.*phinxlog$/', $table) === 1) {
585585
continue;
586586
}
587+
if ($table === 'cake_migrations' || $table === 'cake_seeds') {
588+
continue;
589+
}
587590

588591
$schema[$table] = $collection->describe($table);
589592
}

0 commit comments

Comments
 (0)