@@ -82,7 +82,7 @@ public function printStatus(?string $format = null): array
8282 $ migrations = [];
8383 $ isJson = $ format === 'json ' ;
8484 $ defaultMigrations = $ this ->getMigrations ();
85- if (count ( $ defaultMigrations) ) {
85+ if ($ defaultMigrations ) {
8686 $ env = $ this ->getEnvironment ();
8787 $ versions = $ env ->getVersionLog ();
8888
@@ -361,13 +361,14 @@ public function markVersionsAsMigrated(string $path, array $versions): array
361361 }
362362
363363 /**
364- * Migrate an environment to the specified version.
364+ * Migrate an environment to the specified version or by count of migrations .
365365 *
366366 * @param int|null $version version to migrate to
367367 * @param bool $fake flag that if true, we just record running the migration, but not actually do the migration
368+ * @param int|null $count Number of migrations to run, all migrations will be run if not set and no version is given.
368369 * @return void
369370 */
370- public function migrate (?int $ version = null , bool $ fake = false ): void
371+ public function migrate (?int $ version = null , bool $ fake = false , ? int $ count = null ): void
371372 {
372373 $ migrations = $ this ->getMigrations ();
373374 $ env = $ this ->getEnvironment ();
@@ -409,13 +410,15 @@ public function migrate(?int $version = null, bool $fake = false): void
409410 }
410411
411412 ksort ($ migrations );
413+ $ done = 0 ;
412414 foreach ($ migrations as $ migration ) {
413- if ($ migration ->getVersion () > $ version ) {
415+ if ($ migration ->getVersion () > $ version || ( $ count && $ done >= $ count ) ) {
414416 break ;
415417 }
416418
417419 if (!in_array ($ migration ->getVersion (), $ versions )) {
418420 $ this ->executeMigration ($ migration , MigrationInterface::UP , $ fake );
421+ $ done ++;
419422 }
420423 }
421424 }
@@ -535,6 +538,38 @@ protected function printStatusOutput(string $name, string $status, ?string $dura
535538 );
536539 }
537540
541+ /**
542+ * Rollback an environment by a specific count of migrations.
543+ *
544+ * Note: If the count is greater than the number of migrations, it will rollback all migrations.
545+ *
546+ * @param int $count Count
547+ * @param bool $force Force
548+ * @param bool $fake Flag that if true, we just record running the migration, but not actually do the migration
549+ * @return void
550+ */
551+ public function rollbackByCount (int $ count , bool $ force = false , bool $ fake = false ): void
552+ {
553+ // note that the version log are also indexed by name with the proper ascending order according to the version order
554+ $ executedVersions = $ this ->getEnvironment ()->getVersionLog ();
555+
556+ $ total = count ($ executedVersions );
557+ $ pos = 0 ;
558+ while ($ pos < $ count && $ pos < $ total ) {
559+ array_pop ($ executedVersions );
560+ $ pos ++;
561+ }
562+
563+ if ($ executedVersions ) {
564+ $ last = end ($ executedVersions );
565+ $ target = $ last ['version ' ];
566+ } else {
567+ $ target = 0 ;
568+ }
569+
570+ $ this ->rollback ($ target , $ force , false , $ fake );
571+ }
572+
538573 /**
539574 * Rollback an environment to the specified version.
540575 *
0 commit comments