Browse Source

Fix #17437: Fixed generating namespaced migrations

tags/2.0.24
Bizley 5 years ago committed by Alexander Makarov
parent
commit
e50a07c30c
  1. 1070
      docs/guide-pl/db-migrations.md
  2. 40
      docs/guide/db-migrations.md
  3. 1
      framework/CHANGELOG.md
  4. 11
      framework/console/controllers/BaseMigrateController.php
  5. 50
      framework/console/controllers/MigrateController.php
  6. 5
      framework/views/addColumnMigration.php
  7. 4
      framework/views/dropColumnMigration.php
  8. 2
      tests/data/console/migrate_create/add_columns_fk.php
  9. 2
      tests/data/console/migrate_create/add_columns_prefix.php
  10. 2
      tests/data/console/migrate_create/add_columns_test.php
  11. 4
      tests/data/console/migrate_create/add_two_columns_test.php
  12. 2
      tests/data/console/migrate_create/create_field_with_colon_default_values.php
  13. 2
      tests/data/console/migrate_create/create_fields.php
  14. 2
      tests/data/console/migrate_create/create_foreign_key.php
  15. 2
      tests/data/console/migrate_create/create_id_pk.php
  16. 2
      tests/data/console/migrate_create/create_prefix.php
  17. 2
      tests/data/console/migrate_create/create_test.php
  18. 2
      tests/data/console/migrate_create/create_title_pk.php
  19. 2
      tests/data/console/migrate_create/create_title_with_comma_default_values.php
  20. 2
      tests/data/console/migrate_create/create_unsigned_big_pk.php
  21. 2
      tests/data/console/migrate_create/create_unsigned_pk.php
  22. 2
      tests/data/console/migrate_create/default.php
  23. 2
      tests/data/console/migrate_create/drop_columns_test.php
  24. 2
      tests/data/console/migrate_create/drop_fields.php
  25. 2
      tests/data/console/migrate_create/drop_products_from_store_table.php
  26. 2
      tests/data/console/migrate_create/drop_test.php
  27. 78
      tests/data/console/migrate_create/junction_test.php
  28. 401
      tests/framework/console/controllers/MigrateControllerTest.php
  29. 2
      tests/framework/console/controllers/MigrateControllerTestTrait.php

1070
docs/guide-pl/db-migrations.md

File diff suppressed because it is too large Load Diff

40
docs/guide/db-migrations.md

@ -35,7 +35,7 @@ All these tools are accessible through the command `yii migrate`. In this sectio
how to accomplish various tasks using these tools. You may also get the usage of each tool via the help
command `yii help migrate`.
> Tip: migrations could affect not only database schema but adjust existing data to fit new schema, create RBAC
> Tip: Migrations could affect not only database schema but adjust existing data to fit new schema, create RBAC
hierarchy or clean up cache.
> Note: When manipulating data using a migration you may find that using your [Active Record](db-active-record.md) classes
@ -303,7 +303,7 @@ class m150811_220037_create_post_table extends Migration
}
```
> Note: primary key is added automatically and is named `id` by default. If you want to use another name you may
> Note: Primary key is added automatically and is named `id` by default. If you want to use another name you may
> specify it explicitly like `--fields="name:primaryKey"`.
#### Foreign keys
@ -690,6 +690,7 @@ Below is the list of all these database accessing methods:
* [[yii\db\Migration::insert()|insert()]]: inserting a single row
* [[yii\db\Migration::batchInsert()|batchInsert()]]: inserting multiple rows
* [[yii\db\Migration::update()|update()]]: updating rows
* [[yii\db\Migration::upsert()|upsert()]]: inserting a single row or updating it if it exists (since 2.0.14)
* [[yii\db\Migration::delete()|delete()]]: deleting rows
* [[yii\db\Migration::createTable()|createTable()]]: creating a table
* [[yii\db\Migration::renameTable()|renameTable()]]: renaming a table
@ -722,7 +723,6 @@ Below is the list of all these database accessing methods:
> }
> ```
## Applying Migrations <span id="applying-migrations"></span>
To upgrade a database to its latest structure, you should apply all available new migrations using the following command:
@ -801,7 +801,7 @@ yii migrate/redo 3 # redo the last 3 applied migrations
Since Yii 2.0.13 you can delete all tables and foreign keys from the database and apply all migrations from the beginning.
```
yii migrate/fresh # Truncate the database and apply all migrations from the beginning.
yii migrate/fresh # truncate the database and apply all migrations from the beginning
```
## Listing Migrations <span id="listing-migrations"></span>
@ -935,7 +935,7 @@ return [
];
```
> Note: migrations applied from different namespaces will create a **single** migration history, e.g. you might be
> Note: Migrations applied from different namespaces will create a **single** migration history, e.g. you might be
unable to apply or revert migrations from particular namespace only.
While operating namespaced migrations: creating new, reverting and so on, you should specify full namespace before
@ -943,10 +943,10 @@ migration name. Note that backslash (`\`) symbol is usually considered a special
to escape it properly to avoid shell errors or incorrect behavior. For example:
```
yii migrate/create 'app\\migrations\\createUserTable'
yii migrate/create app\\migrations\\CreateUserTable
```
> Note: migrations specified via [[yii\console\controllers\MigrateController::migrationPath|migrationPath]] can not
> Note: Migrations specified via [[yii\console\controllers\MigrateController::migrationPath|migrationPath]] can not
contain a namespace, namespaced migration can be applied only via [[yii\console\controllers\MigrateController::migrationNamespaces]]
property.
@ -956,6 +956,32 @@ This is mainly added to be used in existing projects which use migrations from d
from external sources, like Yii extensions developed by other developers,
which can not be changed to use namespaces easily when starting to use the new approach.
#### Generating namespaced migrations
Namespaced migrations follow "CamelCase" naming pattern `M<YYMMDDHHMMSS><Name>` (for example `M190720100234CreateUserTable`).
When generating such migration remember that table name will be converted from "CamelCase" format to "underscored". For
example:
```
yii migrate/create app\\migrations\\DropGreenHotelTable
```
generates migration within namespace `app\migrations` dropping table `green_hotel` and
```
yii migrate/create app\\migrations\\CreateBANANATable
```
generates migration within namespace `app\migrations` creating table `b_a_n_a_n_a`.
If table's name is mixed-cased (like `studentsExam`) you need to precede the name with underscore:
```
yii migrate/create app\\migrations\\Create_studentsExamTable
```
This generates migration within namespace `app\migrations` creating table `studentsExam`.
### Separated Migrations <span id="separated-migrations"></span>
Sometimes using single migration history for all project migrations is not desirable. For example: you may install some

1
framework/CHANGELOG.md

@ -7,6 +7,7 @@ Yii Framework 2 Change Log
- Bug #17219: Fixed quoting of table names with spaces in MSSQL (alexkart)
- Bug #10020: Fixed quoting of column names with dots in MSSQL (alexkart)
- Bug #17424: Subdomain support for `User::loginRequired` (alex-code)
- Bug #17437: Fixed generating namespaced migrations (bizley)
2.0.23 July 16, 2019

11
framework/console/controllers/BaseMigrateController.php

@ -17,6 +17,7 @@ use yii\console\ExitCode;
use yii\db\MigrationInterface;
use yii\helpers\Console;
use yii\helpers\FileHelper;
use yii\helpers\Inflector;
/**
* BaseMigrateController is the base class for migrate controllers.
@ -661,17 +662,15 @@ abstract class BaseMigrateController extends Controller
if (strpos($name, '\\') !== false) {
$namespace = substr($name, 0, strrpos($name, '\\'));
$name = substr($name, strrpos($name, '\\') + 1);
} else {
if ($this->migrationPath === null) {
$migrationNamespaces = $this->migrationNamespaces;
$namespace = array_shift($migrationNamespaces);
}
} elseif ($this->migrationPath === null) {
$migrationNamespaces = $this->migrationNamespaces;
$namespace = array_shift($migrationNamespaces);
}
if ($namespace === null) {
$class = 'm' . gmdate('ymd_His') . '_' . $name;
} else {
$class = 'M' . gmdate('ymdHis') . ucfirst($name);
$class = 'M' . gmdate('ymdHis') . Inflector::camelize($name);
}
return [$namespace, $class];

50
framework/console/controllers/MigrateController.php

@ -13,6 +13,7 @@ use yii\db\Query;
use yii\di\Instance;
use yii\helpers\ArrayHelper;
use yii\helpers\Console;
use yii\helpers\Inflector;
/**
* Manages application migrations.
@ -376,6 +377,26 @@ class MigrateController extends BaseMigrateController
}
/**
* Normalizes table name for generator.
* When name is preceded with underscore name case is kept - otherwise it's converted from camelcase to underscored.
* Last underscore is always trimmed so if there should be underscore at the end of name use two of them.
* @param string $name
* @return string
*/
private function normalizeTableName($name)
{
if (substr($name, -1) === '_') {
$name = substr($name, 0, -1);
}
if (strpos($name, '_') === 0) {
return substr($name, 1);
}
return Inflector::underscore($name);
}
/**
* {@inheritdoc}
* @since 2.0.8
*/
@ -386,13 +407,20 @@ class MigrateController extends BaseMigrateController
$foreignKeys = $parsedFields['foreignKeys'];
$name = $params['name'];
if ($params['namespace']) {
$name = substr($name, strrpos($name, '\\') + 1);
}
$templateFile = $this->templateFile;
$table = null;
if (preg_match('/^create_junction(?:_table_for_|_for_|_)(.+)_and_(.+)_tables?$/', $name, $matches)) {
if (preg_match(
'/^create_?junction_?(?:table)?_?(?:for)?(.+)_?and(.+)_?tables?$/i',
$name,
$matches
)) {
$templateFile = $this->generatorTemplateFiles['create_junction'];
$firstTable = $matches[1];
$secondTable = $matches[2];
$firstTable = $this->normalizeTableName($matches[1]);
$secondTable = $this->normalizeTableName($matches[2]);
$fields = array_merge(
[
@ -420,20 +448,20 @@ class MigrateController extends BaseMigrateController
$foreignKeys[$firstTable . '_id']['column'] = null;
$foreignKeys[$secondTable . '_id']['column'] = null;
$table = $firstTable . '_' . $secondTable;
} elseif (preg_match('/^add_(.+)_columns?_to_(.+)_table$/', $name, $matches)) {
} elseif (preg_match('/^add(.+)columns?_?to(.+)table$/i', $name, $matches)) {
$templateFile = $this->generatorTemplateFiles['add_column'];
$table = $matches[2];
} elseif (preg_match('/^drop_(.+)_columns?_from_(.+)_table$/', $name, $matches)) {
$table = $this->normalizeTableName($matches[2]);
} elseif (preg_match('/^drop(.+)columns?_?from(.+)table$/i', $name, $matches)) {
$templateFile = $this->generatorTemplateFiles['drop_column'];
$table = $matches[2];
} elseif (preg_match('/^create_(.+)_table$/', $name, $matches)) {
$table = $this->normalizeTableName($matches[2]);
} elseif (preg_match('/^create(.+)table$/i', $name, $matches)) {
$this->addDefaultPrimaryKey($fields);
$templateFile = $this->generatorTemplateFiles['create_table'];
$table = $matches[1];
} elseif (preg_match('/^drop_(.+)_table$/', $name, $matches)) {
$table = $this->normalizeTableName($matches[1]);
} elseif (preg_match('/^drop(.+)table$/i', $name, $matches)) {
$this->addDefaultPrimaryKey($fields);
$templateFile = $this->generatorTemplateFiles['drop_table'];
$table = $matches[1];
$table = $this->normalizeTableName($matches[1]);
}
foreach ($foreignKeys as $column => $foreignKey) {

5
framework/views/addColumnMigration.php

@ -9,9 +9,6 @@
/* @var $table string the name table */
/* @var $fields array the fields */
preg_match('/^add_(.+)_columns?_to_(.+)_table$/', $name, $matches);
$columns = str_replace('_column_', ', ', $matches[1]);
echo "<?php\n";
if (!empty($namespace)) {
echo "\nnamespace {$namespace};\n";
@ -21,7 +18,7 @@ if (!empty($namespace)) {
use yii\db\Migration;
/**
* Handles adding <?= $columns ?> to table `<?= $table ?>`.
* Handles adding columns to table `<?= $table ?>`.
<?= $this->render('_foreignTables', [
'foreignKeys' => $foreignKeys,
]) ?>

4
framework/views/dropColumnMigration.php

@ -8,8 +8,6 @@
/* @var $namespace string the new migration class namespace */
/* @var $table string the name table */
/* @var $fields array the fields */
preg_match('/^drop_(.+)_columns?_from_(.+)_table$/', $name, $matches);
$columns = $matches[1];
echo "<?php\n";
if (!empty($namespace)) {
@ -20,7 +18,7 @@ if (!empty($namespace)) {
use yii\db\Migration;
/**
* Handles dropping <?= $columns ?> from table `<?= $table ?>`.
* Handles dropping columns from table `<?= $table ?>`.
<?= $this->render('_foreignTables', [
'foreignKeys' => $foreignKeys,
]) ?>

2
tests/data/console/migrate_create/add_columns_fk.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles adding columns to table `{{%{table}}}`.

2
tests/data/console/migrate_create/add_columns_prefix.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles adding columns to table `{{%{table}}}`.

2
tests/data/console/migrate_create/add_columns_test.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles adding columns to table `{{%{table}}}`.

4
tests/data/console/migrate_create/add_two_columns_test.php

@ -8,10 +8,10 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles adding field_1, field_2 to table `{{%{table}}}`.
* Handles adding columns to table `{{%{table}}}`.
*/
class {$class} extends Migration
{

2
tests/data/console/migrate_create/create_field_with_colon_default_values.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the creation of table `{{%test}}`.

2
tests/data/console/migrate_create/create_fields.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the creation of table `{{%{table}}}`.

2
tests/data/console/migrate_create/create_foreign_key.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the creation of table `{{%{table}}}`.

2
tests/data/console/migrate_create/create_id_pk.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the creation of table `{{%{table}}}`.

2
tests/data/console/migrate_create/create_prefix.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the creation of table `{{%{table}}}`.

2
tests/data/console/migrate_create/create_test.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the creation of table `{{%{table}}}`.

2
tests/data/console/migrate_create/create_title_pk.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the creation of table `{{%{table}}}`.

2
tests/data/console/migrate_create/create_title_with_comma_default_values.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the creation of table `{{%test}}`.

2
tests/data/console/migrate_create/create_unsigned_big_pk.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the creation of table `{{%{table}}}`.

2
tests/data/console/migrate_create/create_unsigned_pk.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the creation of table `{{%{table}}}`.

2
tests/data/console/migrate_create/default.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Class {$class}

2
tests/data/console/migrate_create/drop_columns_test.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles dropping columns from table `{{%{table}}}`.

2
tests/data/console/migrate_create/drop_fields.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the dropping of table `{{%{table}}}`.

2
tests/data/console/migrate_create/drop_products_from_store_table.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the dropping of table `{{%{table}}}`.

2
tests/data/console/migrate_create/drop_test.php

@ -8,7 +8,7 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the dropping of table `{{%{table}}}`.

78
tests/data/console/migrate_create/junction_test.php

@ -8,14 +8,14 @@
return <<<CODE
<?php
use yii\db\Migration;
{$namespace}use yii\db\Migration;
/**
* Handles the creation of table `{{%post_tag}}`.
* Handles the creation of table `{{%{junctionTable}}}`.
* Has foreign keys to the tables:
*
* - `{{%post}}`
* - `{{%tag}}`
* - `{{%{firstTable}}}`
* - `{{%{secondTable}}}`
*/
class {$class} extends Migration
{
@ -24,42 +24,42 @@ class {$class} extends Migration
*/
public function safeUp()
{
\$this->createTable('{{%post_tag}}', [
'post_id' => \$this->integer(),
'tag_id' => \$this->integer(),
'PRIMARY KEY(post_id, tag_id)',
\$this->createTable('{{%{junctionTable}}}', [
'{firstTable}_id' => \$this->integer(),
'{secondTable}_id' => \$this->integer(),
'PRIMARY KEY({firstTable}_id, {secondTable}_id)',
]);
// creates index for column `post_id`
// creates index for column `{firstTable}_id`
\$this->createIndex(
'{{%idx-post_tag-post_id}}',
'{{%post_tag}}',
'post_id'
'{{%idx-{junctionTable}-{firstTable}_id}}',
'{{%{junctionTable}}}',
'{firstTable}_id'
);
// add foreign key for table `{{%post}}`
// add foreign key for table `{{%{firstTable}}}`
\$this->addForeignKey(
'{{%fk-post_tag-post_id}}',
'{{%post_tag}}',
'post_id',
'{{%post}}',
'{{%fk-{junctionTable}-{firstTable}_id}}',
'{{%{junctionTable}}}',
'{firstTable}_id',
'{{%{firstTable}}}',
'id',
'CASCADE'
);
// creates index for column `tag_id`
// creates index for column `{secondTable}_id`
\$this->createIndex(
'{{%idx-post_tag-tag_id}}',
'{{%post_tag}}',
'tag_id'
'{{%idx-{junctionTable}-{secondTable}_id}}',
'{{%{junctionTable}}}',
'{secondTable}_id'
);
// add foreign key for table `{{%tag}}`
// add foreign key for table `{{%{secondTable}}}`
\$this->addForeignKey(
'{{%fk-post_tag-tag_id}}',
'{{%post_tag}}',
'tag_id',
'{{%tag}}',
'{{%fk-{junctionTable}-{secondTable}_id}}',
'{{%{junctionTable}}}',
'{secondTable}_id',
'{{%{secondTable}}}',
'id',
'CASCADE'
);
@ -70,31 +70,31 @@ class {$class} extends Migration
*/
public function safeDown()
{
// drops foreign key for table `{{%post}}`
// drops foreign key for table `{{%{firstTable}}}`
\$this->dropForeignKey(
'{{%fk-post_tag-post_id}}',
'{{%post_tag}}'
'{{%fk-{junctionTable}-{firstTable}_id}}',
'{{%{junctionTable}}}'
);
// drops index for column `post_id`
// drops index for column `{firstTable}_id`
\$this->dropIndex(
'{{%idx-post_tag-post_id}}',
'{{%post_tag}}'
'{{%idx-{junctionTable}-{firstTable}_id}}',
'{{%{junctionTable}}}'
);
// drops foreign key for table `{{%tag}}`
// drops foreign key for table `{{%{secondTable}}}`
\$this->dropForeignKey(
'{{%fk-post_tag-tag_id}}',
'{{%post_tag}}'
'{{%fk-{junctionTable}-{secondTable}_id}}',
'{{%{junctionTable}}}'
);
// drops index for column `tag_id`
// drops index for column `{secondTable}_id`
\$this->dropIndex(
'{{%idx-post_tag-tag_id}}',
'{{%post_tag}}'
'{{%idx-{junctionTable}-{secondTable}_id}}',
'{{%{junctionTable}}}'
);
\$this->dropTable('{{%post_tag}}');
\$this->dropTable('{{%{junctionTable}}}');
}
}

401
tests/framework/console/controllers/MigrateControllerTest.php

@ -11,6 +11,7 @@ use Yii;
use yii\console\controllers\MigrateController;
use yii\db\Migration;
use yii\db\Query;
use yii\helpers\Inflector;
use yiiunit\TestCase;
/**
@ -57,96 +58,300 @@ class MigrateControllerTest extends TestCase
return $query->from('migration')->all();
}
public function assertFileContent($expectedFile, $class, $table)
public function assertFileContent($expectedFile, $class, $table, $namespace = null)
{
if ($namespace) {
$namespace = "namespace {$namespace};\n\n";
}
$expected = include Yii::getAlias("@yiiunit/data/console/migrate_create/$expectedFile.php");
$expected = str_replace('{table}', $table, $expected);
$this->assertEqualsWithoutLE($expected, $this->parseNameClassMigration($class, $table));
$this->assertEqualsWithoutLE($expected, $this->parseNameClassMigration($class));
}
protected function assertCommandCreatedFile($expectedFile, $migrationName, $table, $params = [])
{
$class = 'm' . gmdate('ymd_His') . '_' . $migrationName;
$params[0] = $migrationName;
$this->runMigrateControllerAction('create', $params);
$this->assertFileContent($expectedFile, $class, $table);
list($config, $namespace, $class) = $this->prepareMigrationNameData($migrationName);
$this->runMigrateControllerAction('create', $params, $config);
$this->assertFileContent($expectedFile, $class, $table, $namespace);
}
// Tests :
public function assertFileContentJunction($expectedFile, $class, $junctionTable, $firstTable, $secondTable, $namespace = null)
{
if ($namespace) {
$namespace = "namespace {$namespace};\n\n";
}
$expected = include Yii::getAlias("@yiiunit/data/console/migrate_create/$expectedFile.php");
$expected = str_replace(
['{junctionTable}', '{firstTable}', '{secondTable}'],
[$junctionTable, $firstTable, $secondTable],
$expected
);
$this->assertEqualsWithoutLE($expected, $this->parseNameClassMigration($class));
}
public function testGenerateDefaultMigration()
protected function assertCommandCreatedJunctionFile($expectedFile, $migrationName, $junctionTable, $firstTable, $secondTable)
{
$this->assertCommandCreatedFile('default', 'DefaultTest', 'default');
list($config, $namespace, $class) = $this->prepareMigrationNameData($migrationName);
$this->runMigrateControllerAction('create', [$migrationName], $config);
$this->assertFileContentJunction($expectedFile, $class, $junctionTable, $firstTable, $secondTable, $namespace);
}
public function testGenerateCreateMigration()
protected function prepareMigrationNameData($migrationName)
{
$tables = [
'test',
'TEST',
];
foreach ($tables as $table) {
$migrationName = 'create_' . $table . '_table';
$config = [];
$namespace = null;
$lastSlashPosition = strrpos($migrationName, '\\');
if ($lastSlashPosition !== false) {
$config = [
'migrationPath' => null,
'migrationNamespaces' => [$this->migrationNamespace],
];
$class = 'M' . gmdate('ymdHis') . Inflector::camelize(substr($migrationName, $lastSlashPosition + 1));
$namespace = substr($migrationName, 0, $lastSlashPosition);
} else {
$class = 'm' . gmdate('ymd_His') . '_' . $migrationName;
}
$this->assertCommandCreatedFile('create_test', $migrationName, $table);
return [$config, $namespace, $class];
}
$this->assertCommandCreatedFile('create_fields', $migrationName, $table, [
/**
* @return array
*/
public function generateMigrationDataProvider()
{
$params = [
'create_fields' => [
'fields' => 'title:string(10):notNull:unique:defaultValue("test"),
body:text:notNull,
price:money(11,2):notNull,
parenthesis_in_comment:string(255):notNull:comment(\'Name of set (RU)\')',
]);
$this->assertCommandCreatedFile('create_title_pk', $migrationName, $table, [
],
'create_title_pk' => [
'fields' => 'title:primaryKey,body:text:notNull,price:money(11,2)',
]);
$this->assertCommandCreatedFile('create_unsigned_pk', $migrationName, $table, [
],
'create_unsigned_pk' => [
'fields' => 'brand_id:primaryKey:unsigned',
]);
$this->assertCommandCreatedFile('create_unsigned_big_pk', $migrationName, $table, [
],
'create_unsigned_big_pk' => [
'fields' => 'brand_id:bigPrimaryKey:unsigned',
]);
$this->assertCommandCreatedFile('create_id_pk', $migrationName, $table, [
],
'create_id_pk' => [
'fields' => 'id:primaryKey,
address:string,
address2:string,
email:string',
]);
$this->assertCommandCreatedFile('create_foreign_key', $migrationName, $table, [
],
'create_foreign_key' => [
'fields' => 'user_id:integer:foreignKey,
product_id:foreignKey:integer:unsigned:notNull,
order_id:integer:foreignKey(user_order):notNull,
created_at:dateTime:notNull',
]);
$this->assertCommandCreatedFile('create_prefix', $migrationName, $table, [
],
'create_prefix' => [
'useTablePrefix' => true,
'fields' => 'user_id:integer:foreignKey,
product_id:foreignKey:integer:unsigned:notNull,
order_id:integer:foreignKey(user_order):notNull,
created_at:dateTime:notNull',
]);
}
],
'create_title_with_comma_default_values' => [
'fields' => 'title:string(10):notNull:unique:defaultValue(",te,st"),
body:text:notNull:defaultValue(",test"),
test:custom(11,2,"s"):notNull',
],
'create_field_with_colon_default_values' => [
'fields' => 'field_1:dateTime:notNull:defaultValue(\'0000-00-00 00:00:00\'),
field_2:string:defaultValue(\'default:value\')',
],
'drop_fields' => [
'fields' => 'body:text:notNull,price:money(11,2)',
],
'add_columns_test' => [
'fields' => 'title:string(10):notNull,
body:text:notNull,
price:money(11,2):notNull,
created_at:dateTime',
],
'add_columns_fk' => [
'fields' => 'user_id:integer:foreignKey,
product_id:foreignKey:integer:unsigned:notNull,
order_id:integer:foreignKey(user_order):notNull,
created_at:dateTime:notNull',
],
'add_columns_prefix' => [
'useTablePrefix' => true,
'fields' => 'user_id:integer:foreignKey,
product_id:foreignKey:integer:unsigned:notNull,
order_id:integer:foreignKey(user_order):notNull,
created_at:dateTime:notNull',
],
'add_two_columns_test' => [
'fields' => 'field_1:string(10):notNull,
field_2:text:notNull',
],
'drop_columns_test' => [
'fields' => 'title:string(10):notNull,body:text:notNull,
price:money(11,2):notNull,
created_at:dateTime',
],
];
// @see https://github.com/yiisoft/yii2/issues/10876
foreach (['products_from_store', 'products_FROM_store'] as $table) {
$this->assertCommandCreatedFile('drop_products_from_store_table', 'drop_' . $table . '_table', $table);
}
// @see https://github.com/yiisoft/yii2/issues/11461
$this->assertCommandCreatedFile('create_title_with_comma_default_values', 'create_test_table', 'test', [
'fields' => 'title:string(10):notNull:unique:defaultValue(",te,st"),
body:text:notNull:defaultValue(",test"),
test:custom(11,2,"s"):notNull',
]);
return [
['default', 'DefaultTest', 'default', []],
// underscore + table name = case keeped
['create_test', 'create_test_table', 'test', []],
['create_test', 'create_test__table', 'test_', []],
['create_test', 'create_TEST_table', 'TEST', []],
['create_test', 'Create_tEsTTable', 'tEsT', []],
// no underscore + table name = camelcase converted to underscore
['create_test', 'CreateTestTable', 'test', []],
['create_test', 'createTest_table', 'test', []],
['create_test', 'createTe_st_table', 'te_st', []],
['create_test', 'createTest__table', 'test_', []],
['create_test', 'createTESTtable', 't_e_s_t', []],
['create_fields', 'create_test_table', 'test', $params['create_fields']],
['create_fields', 'create_TEST_table', 'TEST', $params['create_fields']],
['create_title_pk', 'create_test_table', 'test', $params['create_title_pk']],
['create_title_pk', 'create_TEST_table', 'TEST', $params['create_title_pk']],
['create_unsigned_pk', 'create_test_table', 'test', $params['create_unsigned_pk']],
['create_unsigned_pk', 'create_TEST_table', 'TEST', $params['create_unsigned_pk']],
['create_unsigned_big_pk', 'create_test_table', 'test', $params['create_unsigned_big_pk']],
['create_unsigned_big_pk', 'create_TEST_table', 'TEST', $params['create_unsigned_big_pk']],
['create_id_pk', 'create_test_table', 'test', $params['create_id_pk']],
['create_id_pk', 'create_TEST_table', 'TEST', $params['create_id_pk']],
['create_foreign_key', 'create_test_table', 'test', $params['create_foreign_key']],
['create_foreign_key', 'create_TEST_table', 'TEST', $params['create_foreign_key']],
['create_prefix', 'create_test_table', 'test', $params['create_prefix']],
['create_prefix', 'create_TEST_table', 'TEST', $params['create_prefix']],
// @see https://github.com/yiisoft/yii2/issues/11461
['create_title_with_comma_default_values', 'create_test_table', 'test', $params['create_title_with_comma_default_values']],
['create_field_with_colon_default_values', 'create_test_table', 'test', $params['create_field_with_colon_default_values']],
['drop_test', 'drop_test_table', 'test', []],
['drop_test', 'drop_test__table', 'test_', []],
['drop_test', 'drop_TEST_table', 'TEST', []],
['drop_test', 'Drop_tEStTable', 'tESt', []],
['drop_test', 'DropTestTable', 'test', []],
['drop_test', 'DropTest_Table', 'test', []],
['drop_test', 'DropTest__Table', 'test_', []],
['drop_test', 'DropTESTtable', 't_e_s_t', []],
['drop_fields', 'drop_test_table', 'test', $params['drop_fields']],
['drop_fields', 'drop_TEST_table', 'TEST', $params['drop_fields']],
// @see https://github.com/yiisoft/yii2/issues/10876
['drop_products_from_store_table', 'drop_products_from_store_table', 'products_from_store', []],
['drop_products_from_store_table', 'drop_products_FROM_store_table', 'products_FROM_store', []],
['add_columns_test', 'add_columns_column_to_test_table', 'test', $params['add_columns_test']],
['add_columns_test', 'add_columns_column_to_test__table', 'test_', $params['add_columns_test']],
['add_columns_test', 'add_columns_column_to_TEST_table', 'TEST', $params['add_columns_test']],
['add_columns_test', 'AddColumns_column_to_teSTtable', 'teST', $params['add_columns_test']],
['add_columns_test', 'AddColumnsColumnTo_tEstTable', 'tEst', $params['add_columns_test']],
['add_columns_test', 'addColumnsColumnToTestTable', 'test', $params['add_columns_test']],
['add_columns_test', 'AddColumnsColumnToTest_Table', 'test', $params['add_columns_test']],
['add_columns_test', 'AddCol__umnsColumnToTest__Table', 'test_', $params['add_columns_test']],
['add_columns_test', 'AddColumnsColumnToTESTTable', 't_e_s_t', $params['add_columns_test']],
['add_columns_fk', 'add_columns_column_to_test_table', 'test', $params['add_columns_fk']],
['add_columns_fk', 'add_columns_column_to_TEST_table', 'TEST', $params['add_columns_fk']],
['add_columns_prefix', 'add_columns_column_to_test_table', 'test', $params['add_columns_prefix']],
['add_columns_prefix', 'add_columns_column_to_TEST_table', 'TEST', $params['add_columns_prefix']],
['add_two_columns_test', 'add_field_1_column_field_2_column_to_test_table', 'test', $params['add_two_columns_test']],
['add_two_columns_test', 'add_field_1_column_field_2_column_to_TEST_table', 'TEST', $params['add_two_columns_test']],
['drop_columns_test', 'drop_columns_column_from_test_table', 'test', $params['add_columns_test']],
['drop_columns_test', 'drop_columns_columns_from_test_table', 'test', $params['add_columns_test']],
['drop_columns_test', 'drop_columns_column_from_test__table', 'test_', $params['add_columns_test']],
['drop_columns_test', 'drop_columns_column_from_TEST_table', 'TEST', $params['add_columns_test']],
['drop_columns_test', 'drop_columns_columns_from_TEST_table', 'TEST', $params['add_columns_test']],
['drop_columns_test', 'dropColumnsColumNSFrom_TEstTable', 'TEst', $params['add_columns_test']],
['drop_columns_test', 'DropFewColumnsFrom_Test_Table', 'Test', $params['add_columns_test']],
['drop_columns_test', 'DropFewColumnsFromTestTable', 'test', $params['add_columns_test']],
['drop_columns_test', 'DropFewColumnsFromTest_Table', 'test', $params['add_columns_test']],
['drop_columns_test', 'DropFewColumnsFromTest__Table', 'test_', $params['add_columns_test']],
['drop_columns_test', 'DropFewColumnsFromTeStTable', 'te_st', $params['add_columns_test']],
];
}
$this->assertCommandCreatedFile('create_field_with_colon_default_values', 'create_test_table', 'test', [
'fields' => 'field_1:dateTime:notNull:defaultValue(\'0000-00-00 00:00:00\'),
field_2:string:defaultValue(\'default:value\')',
]);
/**
* @param string $expectedFile
* @param string $migrationName
* @param string $table
* @param array $params
* @dataProvider generateMigrationDataProvider
*/
public function testGenerateMigration($expectedFile, $migrationName, $table, $params)
{
$this->migrationNamespace = 'yiiunit\runtime\test_migrations';
$this->assertCommandCreatedFile($expectedFile, $migrationName, $table, $params);
$this->assertCommandCreatedFile(
$expectedFile,
$this->migrationNamespace . '\\' . $migrationName,
$table,
$params
);
}
/**
* @return array
*/
public function generateJunctionMigrationDataProvider()
{
return [
['create_junction_post_and_tag_tables', 'post_tag', 'post', 'tag'],
['create_junction_for_post_and_tag_tables', 'post_tag', 'post', 'tag'],
['create_junction_table_for_post_and_tag_tables', 'post_tag', 'post', 'tag'],
['create_junction_table_for_post_and_tag_table', 'post_tag', 'post', 'tag'],
['CreateJunction_postAnd_tagTables', 'post_tag', 'post', 'tag'],
['CreateJunctionFor_postAnd_tagTables', 'post_tag', 'post', 'tag'],
['CreateJunctionTableFor_postAnd_tagTables', 'post_tag', 'post', 'tag'],
['CreateJunctionTableFor_postAnd_tagTable', 'post_tag', 'post', 'tag'],
['CreateJunctionPostAndTagTables', 'post_tag', 'post', 'tag'],
['CreateJunctionPost_AndTag_Tables', 'post_tag', 'post', 'tag'],
['CreateJunctionPost__AndTag__Tables', 'post__tag_', 'post_', 'tag_'],
['CreateJunctionPost__AndTagTables', 'post__tag', 'post_', 'tag'],
['CreateJunctionPostAndTag__Tables', 'post_tag_', 'post', 'tag_'],
['CreateJunctionPostAndTaGTables', 'post_ta_g', 'post', 'ta_g'],
['CreateJunctionPoStAndTagTables', 'po_st_tag', 'po_st', 'tag'],
];
}
/**
* @param string $migrationName
* @param string $junctionTable
* @param string $firstTable
* @param string $secondTable
* @dataProvider generateJunctionMigrationDataProvider
*/
public function testGenerateJunctionMigration($migrationName, $junctionTable, $firstTable, $secondTable)
{
$this->migrationNamespace = 'yiiunit\runtime\test_migrations';
$this->assertCommandCreatedJunctionFile(
'junction_test',
$migrationName,
$junctionTable,
$firstTable,
$secondTable
);
$this->assertCommandCreatedJunctionFile(
'junction_test',
$this->migrationNamespace . '\\' . $migrationName,
$junctionTable,
$firstTable,
$secondTable
);
}
public function testUpdatingLongNamedMigration()
@ -190,100 +395,6 @@ class MigrateControllerTest extends TestCase
$controller->run('create', $params);
}
public function testGenerateDropMigration()
{
$tables = [
'test',
'TEST',
];
foreach ($tables as $table) {
$migrationName = 'drop_' . $table . '_table';
$this->assertCommandCreatedFile('drop_test', $migrationName, $table);
$this->assertCommandCreatedFile('drop_fields', $migrationName, $table, [
'fields' => 'body:text:notNull,price:money(11,2)',
]);
}
// @see https://github.com/yiisoft/yii2/issues/10876
foreach (['products_from_store', 'products_FROM_store'] as $table) {
$this->assertCommandCreatedFile('drop_products_from_store_table', 'drop_' . $table . '_table', $table);
}
}
public function testGenerateAddColumnMigration()
{
$tables = [
'test',
'TEST',
];
foreach ($tables as $table) {
$migrationName = 'add_columns_column_to_' . $table . '_table';
$this->assertCommandCreatedFile('add_columns_test', $migrationName, $table, [
'fields' => 'title:string(10):notNull,
body:text:notNull,
price:money(11,2):notNull,
created_at:dateTime',
]);
$this->assertCommandCreatedFile('add_columns_fk', $migrationName, $table, [
'fields' => 'user_id:integer:foreignKey,
product_id:foreignKey:integer:unsigned:notNull,
order_id:integer:foreignKey(user_order):notNull,
created_at:dateTime:notNull',
]);
$this->assertCommandCreatedFile('add_columns_prefix', $migrationName, $table, [
'useTablePrefix' => true,
'fields' => 'user_id:integer:foreignKey,
product_id:foreignKey:integer:unsigned:notNull,
order_id:integer:foreignKey(user_order):notNull,
created_at:dateTime:notNull',
]);
$this->assertCommandCreatedFile('add_two_columns_test', 'add_field_1_column_field_2_column_to_' . $table . '_table', $table, [
'fields' => 'field_1:string(10):notNull,
field_2:text:notNull',
]);
}
}
public function testGenerateDropColumnMigration()
{
$tables = [
'test',
'TEST',
];
foreach ($tables as $table) {
$migrationNames = [
'drop_columns_column_from_' . $table . '_table',
'drop_columns_columns_from_' . $table . '_table',
];
foreach ($migrationNames as $migrationName) {
$this->assertCommandCreatedFile('drop_columns_test', $migrationName, $table, [
'fields' => 'title:string(10):notNull,body:text:notNull,
price:money(11,2):notNull,
created_at:dateTime',
]);
}
}
}
public function testGenerateCreateJunctionMigration()
{
$migrationNames = [
'create_junction_post_and_tag_tables',
'create_junction_for_post_and_tag_tables',
'create_junction_table_for_post_and_tag_tables',
'create_junction_table_for_post_and_tag_table',
];
foreach ($migrationNames as $migrationName) {
$this->assertCommandCreatedFile('junction_test', $migrationName, 'post_tag');
}
}
/**
* Test the migrate:fresh command.
* @dataProvider refreshMigrationDataProvider

2
tests/framework/console/controllers/MigrateControllerTestTrait.php

@ -172,7 +172,7 @@ CODE;
{
$files = FileHelper::findFiles($this->migrationPath);
$file = file_get_contents($files[0]);
if (preg_match('/class (m\d+_\d+_.*) extends Migration/', $file, $match)) {
if (preg_match('/class (m\d+_?\d+_?.*) extends Migration/i', $file, $match)) {
$file = str_replace($match[1], $class, $file);
}
$this->tearDownMigrationPath();

Loading…
Cancel
Save