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

How to create a new database by Yii2 migration, when I have to use it by default?

我有一个任务描述为 "Creating a new database with Yii2 migration, and use it by default"。但我有一些共谋:我必须在我的 main-local.php 文件中设置至少一个默认数据库才能开始迁移。但我也必须在初始迁移时创建这个数据库。

return [
    'db' => [
        'class' => 'yii\db\Connection',
        'dsn' => 'mysql:host=localhost;dbname=default_base',
        'username' => 'root',
        'password' => '',
        'charset' => 'utf8',
    ],
];

我该如何处理?使用迁移创建数据库并将其设置为默认数据库。

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

public function safeUp()
{
    $this->execute("CREATE DATABASE default_base");
}

我有一个例外:

General error: 1007 Can't create database 'default_base'; database exists

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

时创建这个基础

UPD

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

Exception 'yii\db\Exception' with message 'SQLSTATE[HY000] [1049] Unknown database 'default_base''

我的 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',
            ],

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

您可以在没有数据库名称的情况下定义 DSN:

'dsn' => 'mysql:host=localhost',

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

Yii::$app->preinstallDb->createCommand('CREATE DATABASE default_base')->execute();

但是您不能真正在迁移中创建数据库 - MigrateController 需要 migration table 的数据库来保存迁移历史。您需要在 MigrateController 尝试访问 migration table 之前创建数据库。您可以通过覆盖 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);
    }
}

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

'controllerMap' => [
    'migrate' => [
        'class' => MigrateController::class,
    ],
],

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

我找到了让它对我有用的唯一方法。只是覆盖 MigrateController 中的 init()。 首先,我在 main-local.php 文件中添加了 controllerMap:

'controllerMap' => [
            'migrate' => [
                  'class' => 'console\controllers\MigrateController',]]

然后将新的控制器放入console\controllers:

 namespace console\controllers;
use yii\console\controllers\MigrateController as BasicMigrateController;
use Yii;
class MigrateController extends BasicMigrateController
{
   public function init()
    {
       Yii::$app->preinstallDb->createCommand('CREATE DATABASE IF NOT EXISTS default_base')->execute();
       parent::init();
    }
}