diff --git a/packages/database/src/Migrations/RunnableMigrations.php b/packages/database/src/Migrations/RunnableMigrations.php index 9d3b6b1e4..b82b58ee6 100644 --- a/packages/database/src/Migrations/RunnableMigrations.php +++ b/packages/database/src/Migrations/RunnableMigrations.php @@ -19,7 +19,7 @@ final class RunnableMigrations implements IteratorAggregate public function __construct( private array $migrations = [], ) { - usort($this->migrations, static fn (MigratesUp $a, MigratesUp $b) => $a->name <=> $b->name); + usort($this->migrations, static fn (MigratesUp $a, MigratesUp $b) => strnatcmp($a->name, $b->name)); } public function getIterator(): Traversable diff --git a/packages/database/tests/Migrations/RunnableMigrationsTest.php b/packages/database/tests/Migrations/RunnableMigrationsTest.php new file mode 100644 index 000000000..a15805d7f --- /dev/null +++ b/packages/database/tests/Migrations/RunnableMigrationsTest.php @@ -0,0 +1,73 @@ + $this->createDatabaseMigration($name), $migrationNames); + + $this->assertSame( + expected: $expectedOrder, + actual: array_map( + callback: static fn (MigratesUp $migration) => $migration->name, + array: iterator_to_array(new RunnableMigrations($migrations)), + ), + ); + } + + public static function provide_migrations(): array + { + return [ + [ + 'migrationNames' => [ + 'migration1_1', + 'migration1_10', + '2025-10-12_create_idbn_table', + 'migration1_2', + '2025-01-12_create_author_table', + '2025-08-10_create_user_table', + '2025-08-01_create_book_table', + '2025-08-12_create_chapter_table', + ], + 'expectedOrder' => [ + '2025-01-12_create_author_table', + '2025-08-01_create_book_table', + '2025-08-10_create_user_table', + '2025-08-12_create_chapter_table', + '2025-10-12_create_idbn_table', + 'migration1_1', + 'migration1_2', + 'migration1_10', + ], + ], + ]; + } + + private function createDatabaseMigration(string $name): MigratesUp + { + return new class($name) implements MigratesUp { + public function __construct( + public string $name, + ) {} + + public function up(): QueryStatement + { + return new RawStatement('SELECT 1'); + } + }; + } +}