Final Class Yiisoft\Db\Migration\Command\CreateCommand
| Inheritance | Yiisoft\ |
|---|
Creates a new migration.
This command creates a new migration using the available migration template.
To use it, configure migrations paths (newMigrationPath and sourcePaths) in params.php file, in your application.
'yiisoft/db-migration' => [
'newMigrationNamespace' => '',
'newMigrationPath' => '',
'sourceNamespaces' => [],
'sourcePaths' => [],
],
After using this command, developers should modify the created migration skeleton by filling up the actual migration logic.
./yii migrate:create table --command=table
To generate a namespaced migration, you should specify a namespace before the migration's name.
Note that backslash (\) is usually considered a special character in the shell, so you need to escape it properly
to avoid shell errors or incorrect behavior.
For example:
./yii migrate:create post --command=table --namespace=Yiisoft\\Db\\Migration\\Migration
./yii migrate:create post --command=table --path=@root/migrations/blog
In case {@see \
Public Methods
| Method | Description | Defined By |
|---|---|---|
| __construct() | Yiisoft\ |
Protected Methods
Constants
| Constant | Value | Description | Defined By |
|---|---|---|---|
| AVAILABLE_COMMANDS | [ 'create', 'table', 'dropTable', 'addColumn', 'dropColumn', 'junction', ] | Yiisoft\ |
Method Details
| public mixed __construct ( Yiisoft\ | ||
| $createService | Yiisoft\ |
|
| $migrationService | Yiisoft\ |
|
| $migrator | Yiisoft\ |
|
| $additionalDatabases | ?\ |
|
public function __construct(
private readonly CreateService $createService,
private readonly MigrationService $migrationService,
private readonly Migrator $migrator,
?DatabaseRegistry $additionalDatabases = null,
) {
parent::__construct($additionalDatabases);
}
| protected void configure ( ) |
protected function configure(): void
{
$this
->addArgument('name', InputArgument::REQUIRED, 'Table name to generate migration for.')
->addOption('command', 'c', InputOption::VALUE_REQUIRED, 'Command to execute.', 'create')
->addOption('fields', 'f', InputOption::VALUE_REQUIRED, 'Table fields to generate.')
->addOption('table-comment', null, InputOption::VALUE_REQUIRED, 'Table comment.')
->addOption('and', null, InputOption::VALUE_REQUIRED, 'And junction.')
->addOption('path', null, InputOption::VALUE_REQUIRED, 'Path to migration directory.')
->addOption('namespace', 'ns', InputOption::VALUE_REQUIRED, 'Migration file namespace.')
->addOption(
'transactional',
null,
InputOption::VALUE_NEGATABLE,
'Generate a transactional migration. If omitted, use the configured mode or template default.',
)
->setHelp('This command generates new migration file.');
}
| protected Yiisoft\ | ||
| $setup | Yiisoft\ |
|
protected function createContext(DatabaseSetup $setup): CreateContext
{
return new CreateContext(
$setup->migrator,
$setup->migrationService,
new CreateService(
$setup->config->db,
$setup->config->useTablePrefix,
$setup->config->newMigrationTransactional,
),
);
}
| protected Yiisoft\ |
protected function createDefaultContext(): CreateContext
{
return new CreateContext($this->migrator, $this->migrationService, $this->createService);
}
| 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 integer 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->createService->setIo($io);
$context->migrationService->databaseConnection();
/** @var string|null $path */
$path = $input->getOption('path');
/** @var string|null $namespace */
$namespace = $input->getOption('namespace');
if ($path !== null || $namespace !== null) {
$context->migrationService->setNewMigrationPath((string) $path);
$context->migrationService->setNewMigrationNamespace((string) $namespace);
} else {
$namespace = $context->migrationService->getNewMigrationNamespace();
}
if ($context->migrationService->before($this->getName() ?? '') === Command::INVALID) {
return Command::INVALID;
}
/** @var string $table */
$table = $input->getArgument('name');
if (!preg_match('/^[\w\\\\]+$/' , $table)) {
$io->error(
'The migration name should contain letters, digits, underscore and/or backslash characters only.',
);
return Command::INVALID;
}
/** @var string $command */
$command = $input->getOption('command');
if (!in_array($command, self::AVAILABLE_COMMANDS, true)) {
$io->error(
"Command not found \"$command\". Available commands: " . implode(', ', self::AVAILABLE_COMMANDS) . '.',
);
return Command::INVALID;
}
/** @var string|null $and */
$and = $input->getOption('and');
$name = $this->generateName($command, $table, $and);
$className = $context->migrationService->generateClassName($name);
$nameLimit = $context->migrator->getMigrationNameLimit();
if ($nameLimit !== 0 && strlen($className) > $nameLimit) {
$io->error('The migration name is too long.');
return Command::INVALID;
}
try {
$migrationPath = $context->migrationService->findMigrationPath();
} catch (LogicException $e) {
$io->error($e->getMessage());
return Command::INVALID;
}
if (!is_dir($migrationPath)) {
$io->error("Invalid path directory \"$migrationPath\"");
return Command::INVALID;
}
/** @var string|null $fields */
$fields = $input->getOption('fields');
/** @var string|null $tableComment */
$tableComment = $input->getOption('table-comment');
/** @var bool|null $transactional */
$transactional = $input->getOption('transactional');
$content = $context->createService->run(
$command,
$table,
$className,
$namespace,
$fields,
$and,
$tableComment,
$transactional,
);
$file = $migrationPath . DIRECTORY_SEPARATOR . $className . '.php';
file_put_contents($file, $content, LOCK_EX);
$output->writeln("\n\t<info>$className</info>" );
$output->writeln("\n" );
$io->success('New migration created 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() !== [];
}
| protected array resolveDatabaseNamesWithMissingOption ( \ | ||
| $input | \ |
|
protected function resolveDatabaseNamesWithMissingOption(InputInterface $input): array
{
return [DatabaseRegistry::DEFAULT_DATABASE];
}
User Contributed Notes
Leave a comment
Join the conversation to share a note.