当我必须默认使用它时,如何通过 Yii2 迁移创建新数据库?

Val*_*lik 0 php mysql database-migration yii2 yii2-advanced-app

我有一个任务,描述为“使用 Yii2 迁移创建新数据库,并默认使用它”。但我有一些勾结:我必须在我的main-local.php文件中设置至少一个默认数据库才能开始迁移。但我也必须通过初始迁移创建这个数据库。

return [
    'db' => [
        'class' => 'yii\db\Connection',
        'dsn' => 'mysql:host=localhost;dbname=default_base',
        'username' => 'root',
        'password' => '',
        'charset' => 'utf8',
    ],
];
Run Code Online (Sandbox Code Playgroud)

我该如何处理?创建一个带有迁移的数据库并设置为默认数据库。

当我执行迁移时(迁移文件中有代码):

public function safeUp()
{
    $this->execute("CREATE DATABASE default_base");
}
Run Code Online (Sandbox Code Playgroud)

我有一个例外:

General error: 1007 Can't create database 'default_base'; database exists
Run Code Online (Sandbox Code Playgroud)

我意识到这是因为我已经在 phpmyadmin 中创建了 default_base(单击按钮“创建数据库”),并将其与我的main-local.php文件中的应用程序连接。但是我只需要在执行yii migrate.

UPD

我已经尝试了 rob006 推荐的方式,但出现连接错误

Exception 'yii\db\Exception' with message 'SQLSTATE[HY000] [1049] Unknown database 'default_base''
Run Code Online (Sandbox Code Playgroud)

我的 main-local.php 看起来就像 rob006 推荐的那样,但我仍然无法迁移。仅当我设置时才有效:

'preinstallDb' => [
                  'class'    => 'yii\db\Connection',
                  'dsn'      => 'mysql:host=localhost',
                  'username' => 'root',
                  'password' => '',
                  'charset'  => 'utf8',
            ],
            'db'           => [
                  'class'    => 'yii\db\Connection',
                  'dsn'      => 'mysql:host=localhost;dbname=already_exists_db',
                  'username' => 'root',
                  'password' => '',
                  'charset'  => 'utf8',
            ],
Run Code Online (Sandbox Code Playgroud)

使用已经存在的数据库。我又做错了什么?

rob*_*006 5

您可以定义没有数据库名称的 DSN:

'dsn' => 'mysql:host=localhost',
Run Code Online (Sandbox Code Playgroud)

并使用此连接创建数据库。

Yii::$app->preinstallDb->createCommand('CREATE DATABASE default_base')->execute();
Run Code Online (Sandbox Code Playgroud)

但是,您无法在迁移中真正创建数据库 -MigrateController需要migration表的数据库来保存迁移历史记录。在MigrateController尝试访问migration表之前,您需要创建数据库。您可以通过覆盖来做到这一点MigrateController::getMigrationHistory()

class MigrateController extends \yii\console\controllers\MigrateController {

    protected function getMigrationHistory($limit) {
        Yii::$app->preinstallDb->createCommand('CREATE DATABASE IF NOT EXISTS default_base')->execute();

        return parent::getMigrationHistory($limit);
    }
}
Run Code Online (Sandbox Code Playgroud)

并在控制台应用程序配置中使用您的控制器:

'controllerMap' => [
    'migrate' => [
        'class' => MigrateController::class,
    ],
],
Run Code Online (Sandbox Code Playgroud)

但老实说,这是带有大量硬编码的丑陋解决方案,创建一些设置实用程序可能会更好,该实用程序将在主应用程序之外执行数据库创建。通常出于安全原因,应用程序使用的数据库用户甚至不应该具有创建数据库的权限,因此您可能会重新考虑您的用例 - 您真的需要通过应用程序创建数据库吗?