postgres->query( <<<'SQL' create table if not exists migration ( file text not null primary key, migrated_at timestamptz not null ) SQL, ); $files = Finder::create() ->in($this->directory) ->path('Migration') ->name('*.sql') ->sortByName(useNaturalSort: true); foreach ($files as $file) { $this->migrateFile($file); } } private function migrateFile(SplFileInfo $file): void { $transaction = $this->postgres->beginTransaction(); $result = $transaction->execute( <<<'SQL' insert into migration (file, migrated_at) values (?, now()) on conflict (file) do nothing SQL, [$file->getRelativePathname()], ); if ($result->getRowCount() === 0) { $transaction->rollback(); return; } $transaction->query($file->getContents()); $transaction->commit(); } }