Final Class Yiisoft\Db\Migration\Command\DownCommand
| Inheritance | Yiisoft\ |
|---|
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
Public Methods
| Method | Description | Defined By |
|---|---|---|
| __construct() | Yiisoft\ |
Protected Methods
| Method | Description | Defined By |
|---|---|---|
| configure() | Yiisoft\ |
|
| createContext() | Yiisoft\ |
|
| createDefaultContext() | Yiisoft\ |
|
| execute() | Yiisoft\ |
|
| executeForDatabase() | Yiisoft\ |
|
| getAvailableDatabaseNames() | Yiisoft\ |
|
| isMultipleDatabases() | Yiisoft\ |
|
| resolveDatabaseNamesWithMissingOption() | Resolves the database names or returns a message indicating that an option is missing if multiple databases are configured. | Yiisoft\ |
Method Details
| public mixed __construct ( Yiisoft\ | ||
| $downRunner | Yiisoft\ |
|
| $migrationService | Yiisoft\ |
|
| $migrator | Yiisoft\ |
|
| $additionalDatabases | ?\ |
|
public function __construct(
private readonly DownRunner $downRunner,
private readonly MigrationService $migrationService,
private readonly Migrator $migrator,
?DatabaseRegistry $additionalDatabases = null,
) {
parent::__construct($additionalDatabases);
}
| 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.');
}
| protected Yiisoft\ | ||
| $setup | Yiisoft\ |
|
protected function createContext(DatabaseSetup $setup): DownContext
{
return new DownContext($setup->migrator, $setup->migrationService, new DownRunner($setup->migrator));
}
| protected Yiisoft\ |
protected function createDefaultContext(): DownContext
{
return new DownContext($this->migrator, $this->migrationService, $this->downRunner);
}
| protected integer execute ( \ | ||
| $input | \ |
|
| $output | \ |
|
final protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$names = $this->resolveDatabaseNames($input);
if (is_string($names)) {
$io->error($names);
return Command::INVALID;
}
$multipleDatabases = $this->isMultipleDatabases();
$hasResults = false;
foreach ($names as $name) {
if (!$multipleDatabases || $name === DatabaseRegistry::DEFAULT_DATABASE) {
$context = $this->createDefaultContext();
} else {
/** @psalm-var DatabaseRegistry $this->additionalDatabases */
$context = $this->createContext($this->additionalDatabases->createSetup($name));
}
if ($multipleDatabases) {
$io->section('Database: ' . OutputFormatter::escape($name));
}
$status = $this->executeForDatabase($input, $output, $context);
if ($status === null) {
continue;
}
if ($status !== Command::SUCCESS) {
return $status;
}
$hasResults = true;
}
return $hasResults ? Command::SUCCESS : Command::FAILURE;
}
| protected ?int executeForDatabase ( \ | ||
| $input | \ |
|
| $output | \ |
|
| $context | object | |
protected function executeForDatabase(
InputInterface $input,
OutputInterface $output,
object $context,
): ?int {
$io = new SymfonyStyle($input, $output);
$context->migrator->setIo($io);
$context->migrationService->setIo($io);
$context->downRunner->setIo($io);
$context->migrationService->databaseConnection();
$context->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.');
return Command::INVALID;
}
/** @var string[] $paths */
$paths = $input->getOption('path');
/** @var string[] $namespaces */
$namespaces = $input->getOption('namespace');
if (!empty($paths) || !empty($namespaces)) {
$migrations = $context->migrator->getHistory();
$migrations = array_keys($migrations);
$migrations = $context->migrationService->filterMigrations($migrations, $namespaces, $paths);
if (empty($migrations)) {
$io->warning('No applied migrations found.');
return null;
}
if ($limit !== null) {
$migrations = array_slice($migrations, 0, $limit);
}
} else {
$migrations = $context->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 null;
}
$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 ($input->getOption('force-yes') || $io->confirm("Revert the above $migrationWord?")) {
$instances = $context->migrationService->makeRevertibleMigrations($migrations);
$migrationWas = ($countMigrations === 1 ? 'migration was' : 'migrations were');
foreach ($instances as $i => $instance) {
try {
$context->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.');
}
return Command::SUCCESS;
}
| protected string[] getAvailableDatabaseNames ( ) |
protected function getAvailableDatabaseNames(): array
{
return [DatabaseRegistry::DEFAULT_DATABASE, ...($this->additionalDatabases?->getNames() ?? [])];
}
| protected boolean isMultipleDatabases ( ) |
protected function isMultipleDatabases(): bool
{
return $this->additionalDatabases !== null && $this->additionalDatabases->getNames() !== [];
}
Defined in:
Yiisoft\
Resolves the database names or returns a message indicating that an option is missing if multiple databases are configured.
| protected string[]|string resolveDatabaseNamesWithMissingOption ( \ | ||
| $input | \ |
The input interface containing the command options and arguments. |
protected function resolveDatabaseNamesWithMissingOption(InputInterface $input): array|string
{
if (!$this->isMultipleDatabases()) {
return [DatabaseRegistry::DEFAULT_DATABASE];
}
return 'The --db option is required when multiple databases are configured.';
}
User Contributed Notes
Leave a comment
Join the conversation to share a note.