0 follower

Final Class Yiisoft\Db\Migration\Command\DownCommand

InheritanceYiisoft\Db\Migration\Command\DownCommand » Symfony\Component\Console\Command\Command

Reverts the specified number of latest migrations.

For example:

./yii migrate:down                                           # revert the last migration
./yii migrate:down --limit=3                                 # revert last 3 migrations
./yii migrate:down --all                                     # revert all migrations
./yii migrate:down --path=@vendor/yiisoft/rbac-db/migrations # revert the last migration from the directory
./yii migrate:down --namespace=Yiisoft\\Rbac\\Db\\Migrations # revert the last migration from the namespace

# revert migrations from multiple directories and namespaces
./yii migrate:down --path=@vendor/yiisoft/rbac-db/migrations --path=@vendor/yiisoft/cache-db/migrations
./yii migrate:down --namespace=Yiisoft\\Rbac\\Db\\Migrations --namespace=Yiisoft\\Cache\\Db\\Migrations

Method Details

Hide inherited methods

__construct() public method

public mixed __construct ( Yiisoft\Db\Migration\Runner\DownRunner $downRunner, Yiisoft\Db\Migration\Service\MigrationService $migrationService, Yiisoft\Db\Migration\Migrator $migrator )
$downRunner Yiisoft\Db\Migration\Runner\DownRunner
$migrationService Yiisoft\Db\Migration\Service\MigrationService
$migrator Yiisoft\Db\Migration\Migrator

                public function __construct(
    private readonly DownRunner $downRunner,
    private readonly MigrationService $migrationService,
    private readonly Migrator $migrator,
) {
    parent::__construct();
}

            
configure() protected method

protected void configure ( )

                protected function configure(): void
{
    $this
        ->addOption('limit', 'l', InputOption::VALUE_REQUIRED, 'Number of migrations to revert.', 1)
        ->addOption('all', 'a', InputOption::VALUE_NONE, 'Revert all migrations.')
        ->addOption('path', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Path to migrations to revert.')
        ->addOption('namespace', 'ns', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Namespace of migrations to revert.')
        ->addOption('force-yes', 'y', InputOption::VALUE_NONE, 'Force yes to all questions.');
}

            
execute() protected method

protected integer execute ( \Symfony\Component\Console\Input\InputInterface $input, \Symfony\Component\Console\Output\OutputInterface $output )
$input \Symfony\Component\Console\Input\InputInterface
$output \Symfony\Component\Console\Output\OutputInterface

                protected function execute(InputInterface $input, OutputInterface $output): int
{
    $io = new SymfonyStyle($input, $output);
    $this->migrator->setIo($io);
    $this->migrationService->setIo($io);
    $this->downRunner->setIo($io);
    $this->migrationService->before($this->getName() ?? '');
    $limit = !$input->getOption('all')
        ? (int) $input->getOption('limit')
        : null;
    if ($limit !== null && $limit <= 0) {
        $io->error('The limit option must be greater than 0.');
        $this->migrationService->databaseConnection();
        return Command::INVALID;
    }
    /** @var string[] $paths */
    $paths = $input->getOption('path');
    /** @var string[] $namespaces */
    $namespaces = $input->getOption('namespace');
    if (!empty($paths) || !empty($namespaces)) {
        $migrations = $this->migrator->getHistory();
        $migrations = array_keys($migrations);
        $migrations = $this->migrationService->filterMigrations($migrations, $namespaces, $paths);
        if (empty($migrations)) {
            $io->warning('No applied migrations found.');
            return Command::FAILURE;
        }
        if ($limit !== null) {
            $migrations = array_slice($migrations, 0, $limit);
        }
    } else {
        $migrations = $this->migrator->getHistory($limit);
        if (empty($migrations)) {
            $output->writeln("<fg=yellow> >>> Apply at least one migration first.</>\n");
            $io->warning('No migration has been done before.');
            return Command::FAILURE;
        }
        $migrations = array_keys($migrations);
    }
    $countMigrations = count($migrations);
    $migrationWord = $countMigrations === 1 ? 'migration' : 'migrations';
    $output->writeln(
        "<fg=yellow>Total $countMigrations $migrationWord to be reverted:</>\n",
    );
    foreach ($migrations as $i => $migration) {
        $output->writeln("\t<fg=yellow>" . ($i + 1) . ". $migration</>");
    }
    if ($this->confirm($input, $output, $migrationWord)) {
        $instances = $this->migrationService->makeRevertibleMigrations($migrations);
        $migrationWas = ($countMigrations === 1 ? 'migration was' : 'migrations were');
        foreach ($instances as $i => $instance) {
            try {
                $this->downRunner->run($instance, $i + 1);
            } catch (Throwable $e) {
                $output->writeln("\n<fg=yellow> >>> Total $i out of $countMigrations $migrationWas reverted.</>\n");
                $io->error($i > 0 ? 'Partially reverted.' : 'Not reverted.');
                throw $e;
            }
        }
        $output->writeln("\n<fg=green> >>> [OK] $countMigrations $migrationWas reverted.\n");
        $io->success('Migrated down successfully.');
    }
    $this->migrationService->databaseConnection();
    return Command::SUCCESS;
}