【问题标题】:Laravel: Run migrations on another databaseLaravel:在另一个数据库上运行迁移
【发布时间】: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。每个用户都可以为自己创建网站,我们希望每个网站都有自己独立的数据库。在这段代码中,我为每个用户创建了单独的数据库并将其数据保存在默认数据库中,现在我想在这个新数据库上运行一些迁移以创建新的数据库模式。

标签: laravel laravel-4 database-migration multi-tenant


【解决方案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;
        }
        

        【讨论】:

        • 这不仅适用于迁移,而且适用于任何地方。
        猜你喜欢
        • 2017-05-25
        • 1970-01-01
        • 2020-03-16
        • 1970-01-01
        • 2023-03-20
        • 1970-01-01
        • 2016-01-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多