Laravel:在另一个数据库上运行迁移

Posted

技术标签:

【中文标题】Laravel:在另一个数据库上运行迁移【英文标题】:Laravel: Run migrations on another database 【发布时间】:2014-11-15 03:16:23 【问题描述】:

在我的应用中,每个用户都有自己的数据库,该数据库是在用户注册时创建的。连接和数据库数据(数据库名称、用户名、密码)保存在默认数据库的表中。

try
    DB::transaction(function() 

        $website = new Website();
        $website->user_id = Auth::get()->id;
        $website->save();

        $database_name = 'website_'.$website->id;

        DB::statement(DB::raw('CREATE DATABASE ' . $database_name));

        $websiteDatabase = new WebsiteDatabase();
        $websiteDatabase->website_id = $website->id;
        $websiteDatabase->database_name = $database_name;
        $websiteDatabase->save();

    );
 catch(\Exception $e) 
    echo $e->getMessage();

现在我想在新用户的数据库创建后对其进行一些迁移。

有可能吗?

谢谢

【问题讨论】:

为您的数据库添加 laravel 环境并在这些环境中调用 artisan 工具?为什么要为每个客户创建一个数据库?对于 Laravel 应用来说,这听起来像是一个通常的决定。 我们的网络应用类似于wix.com。每个用户都可以为自己创建网站,我们希望每个网站都有自己独立的数据库。在这段代码中,我为每个用户创建了单独的数据库并将其数据保存在默认数据库中,现在我想在这个新数据库上运行一些迁移以创建新的数据库模式。 【参考方案1】:

如果您将数据库配置放在database.php 文件中,这可以帮助您:

php artisan migrate --database=**otherDatabase**

【讨论】:

我在 Laravel Forge 部署脚本上设置了两个迁移,分别为 php artisan migratephp artisan migrate --database=arc_mysql 带有 4 个星号?你不能认真【参考方案2】:

在您的 app/config/database.php 中,您必须:

<?php
return array(

    'default' => 'mysql',

    'connections' => array(

        # Our primary database connection
        'mysql' => array(
            'driver'    => 'mysql',
            'host'      => 'host1',
            'database'  => 'database1',
            'username'  => 'user1',
            'password'  => 'pass1'
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
        ),

        # Our secondary database connection
        'mysql2' => array(
            'driver'    => 'mysql',
            'host'      => 'host2',
            'database'  => 'database2',
            'username'  => 'user2',
            'password'  => 'pass2'
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
        ),
    ),
);

现在您在迁移中准备了两个数据库连接,您可以执行以下操作:

Schema::connection('mysql2')->create('some_table', function($table)

    $table->increments('id');
);

这应该可行。 更多信息:http://fideloper.com/laravel-multiple-database-connections

【讨论】:

我的配置文件中没有辅助数据库连接。数据库连接详细信息保存在主数据库中! 我认为您应该澄清您的问题,并可能显示一些代码以使其易于理解...【参考方案3】:

如果你的意思是使用不同的数据库连接,它存在于文档中:

Schema::connection('foo')->create('users', function (Blueprint $table) 
    $table->bigIncrements('id');
);

【讨论】:

【参考方案4】:

我有同样的问题,我的解决方案是先使用Config::set 更改数据库,然后运行Artisan::call("migrate")。所以根据你的代码:

DB::statement(DB::raw('CREATE DATABASE ' . $database_name));
Config::set('database.connections.mysql.database', $database_name);
Artisan::call("migrate --database=mysql");

配置仅在您的会话中更改,然后稍后重置为您当前的设置。

【讨论】:

【参考方案5】:

我实际上遇到了同样的问题,Joe 的答案在我的情况下不起作用,因为我有不同的数据库连接(所以不同的主机、端口、用户和密码)。

因此迁移必须一直进行大量的重新连接:

迁移从默认数据库开始(在我的例子中是 client_1) 从表 migrationsclients 获取内容 断开默认数据库 连接到client_2的数据库,运行迁移部分,断开client_2 再次连接默认数据库,存储迁移“日志”

然后为每个客户端循环它。

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    
        $defaultConnection = BackendConfig::getDatabaseConfigArray();
        $clients = ClientController::returnDatabasesForArtisan();

        foreach ($clients as $client) 
            BackendConfig::setDatabaseFromClient($client);

            Schema::create('newtable', function (Blueprint $table) 
                $table->increments('id')->unsigned();
                $table->timestamps();
            );
            BackendConfig::setDatabaseFromArray($defaultConnection);
        
    

还有存放魔法的类:

class BackendConfig

    public static function getDatabaseConfigArray($client_id = 1)
    
        $connection = config('database.default');

        return [
            'id' => $client_id,
            'host' => config("database.connections.$connection.host"),
            'port' => config("database.connections.$connection.port"),
            'username' => config("database.connections.$connection.username"),
            'password' => config("database.connections.$connection.password"),
        ];
    

    public static function setDatabaseFromArray($array)
    
        self::setDatabase($array['id'], $array['host'], $array['port'], $array['username'], $array['password'], true);
        DB::disconnect();
    

    public static function setDatabaseFromClient(Client $client)
    
        DB::disconnect();
        self::setDatabase($client->id, $client->database->host, $client->database->port, $client->database->username, $client->database->password, true);
    

    public static function setDatabase($client_id, $host, $port, $username, $password)
    
        $connection = config('database.default');

        $database_name = $connection . '_' . $client_id;

        config([
            "database.connections.$connection.database" => $database_name,
            "database.connections.$connection.host" => $host,
            "database.connections.$connection.port" => $port,
            "database.connections.$connection.username" => $username,
            "database.connections.$connection.password" => $password,
        ]);

使用这个解决方案,我可以在每个客户端上运行完全相同的迁移,但迁移只是存储在我的主客户端 client_1 中。

不过,注意两个DB::disconnect();。如果没有这些,情况会变得糟糕,因为迁移日志会存储在另一个客户端的数据库等中。

啊,顺便说一句,ClientController 并没有什么特别之处:

public static function returnDatabasesForArtisan()

    return Client::select('*')->with('database')->get();

【讨论】:

【参考方案6】:

记住哪个迁移对应哪个数据库是很乏味的。

对于 Laravel 5.5,我使用了这种方法:

public function up()


 // this line is important
  Illuminate\Support\Facades\DB::setDefaultConnection('anotherDatabaseConnection');


   Schema::table('product',
          function (Blueprint $table)
     
        $table->string('public_id', 85)->nullable()->after('ProductID');
     );

  // this line is important, Probably you need to set this to 'mysql'
   Illuminate\Support\Facades\DB::setDefaultConnection('nameOfYourDefaultDatabaseConnection');

所有迁移都可以自动运行,而无需在运行时手动指定数据库。

请注意,迁移表存储在您的默认数据库中。

【讨论】:

当然,虽然本机不知道【参考方案7】:

我想我终于弄清楚了这个烂摊子......这个解决方案不需要为每个租户的数据库进行配置,并且只需要运行一次。

class MigrationBlah extends Migration 
  public function up() 
    $dbs = DB::connection('tenants')->table('tenants')->get();
    foreach ($dbs as $db) 
      Schema::table($db->database . '.bodegausuarios', function($table)
        $table->foreign('usuario')->references('usuarioid')->on('authusuarios');
      );
    
  

我的 database.php 上有一个名为“tenants”的连接,其中包含我所有租户的数据库名称。我也将默认连接设置为我的租户数据库。该数据库负责处理迁移表。

使用 foreach 语句,它会遍历租户数据库并在每个数据库上运行迁移。

在您的默认连接上,您应该配置一个有权访问所有租户数据库的用户才能正常工作。

【讨论】:

通过使用这种方法,您无法为单个租户迁移。【参考方案8】:

最好的解决方案是您可以在 AppServiceProvide

上调用此方法

它是此类问题的最佳解决方案。我在我的项目中使用它。就我而言,我有两个环境 DevelopmentProduction。因此,当项目处于开发模式时,它将在本地服务器上查看其他实时服务器。所以你可以在这里设置dynamic-DB概念。

您必须创建一个函数,然后您必须在 App\Providers\AppServiceProvide.php

上的 boot() 函数 中调用它
    public function boot()
    
       DBConnection();

    

我为此创建了 Helper 文件。所以我在 helper.php

中的代码
 function DBConnection()
 
  if( env('APP_ENV') ==  'local' )
      $databse_name = "test_me";
       $host = '127.0.0.1';
       $user="root";
      $password="";
   
    else
  
    $databse_name = 'tic_tac';
    $host = 'localhost';
    $user="";
    $password="";
  
    $state = true;
   try 
      Config::set('database.connections.myConnection', array(
        'driver'    => 'mysql',
        'host'      => $host,
        'database'  => $databse_name,
        'username'  => $user,
        'password'  => $password,
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix'    => '',
        'strict' => false,
     ));
    /* \DB::setDefaultConnection('myConnection');
      $state = \DB::connection()->getPdo();*/

     Config::set('database.connections.myConnection.database', $databse_name);
     \DB::setDefaultConnection('myConnection');
      \DB::reconnect('myConnection');

    catch( \Exception $e) 
      $state = false;
   
 return $state;

【讨论】:

这不仅适用于迁移,而且适用于任何地方。

以上是关于Laravel:在另一个数据库上运行迁移的主要内容,如果未能解决你的问题,请参考以下文章

如何在 laravel 中运行特定迁移 [重复]

Laravel 5:在服务器环境而不是本地运行迁移

MySQL数据库的Laravel迁移“无法添加外键约束”错误

带有 Sqlite 错误的 Laravel 迁移:typeSet 不存在

Laravel php artisan 迁移空数据库上的错误

laravel 5.4 迁移问题