web-dev-qa-db-ja.com

Laravel:別のデータベースで移行を実行する

私のアプリでは、すべてのユーザーが、ユーザー登録時に作成された独自のデータベースを持っています。接続とデータベースデータ(データベース名、ユーザー名、パスワード)は、デフォルトデータベースのテーブルに保存されます。

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();
}

次に、新しいユーザーのデータベースを作成した後、そのデータベースでいくつかの移行を実行したいと思います。

出来ますか?

ありがとう

17
Pooya Saberian

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'    => '',
        ),
    ),
);

移行で2つのデータベース接続を準備したので、次のことができます。

Schema::connection('mysql2')->create('some_table', function($table)
{
    $table->increments('id');
});

これはうまくいくはずです。詳細: http://fideloper.com/laravel-multiple-database-connections

35
pietrovismara

データベース構成をdatabase.phpファイル、これはあなたを助けることができます:

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

実際には同じ問題に直面し、データベース接続が異なるため(ホスト、ポート、ユーザー、パスが異なるため)、ジョーの答えは私の場合には機能しませんでした。

したがって、移行では常に多くの再接続を行う必要があります。

  • 移行はデフォルトのデータベースから始まります(私の場合はclient_1
  • テーブルmigrationsおよびclientsからデータをフェッチします
  • デフォルトのデータベースを切断する
  • 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に格納されるだけです。

ただし、2つのDB::disconnect();に注意してください。移行ログは別のクライアントのデータベースなどに保存されるため、このような状況がなければ、状況が台無しになります。

ああ、ところでClientControllerは特別なことは何もしません:

_public static function returnDatabasesForArtisan()
{
    return Client::select('*')->with('database')->get();
}
_
2
andi79h

同じ問題があります。私の解決策は、最初に_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");
_

構成はセッションでのみ変更され、後で現在の設定としてリセットされます。

最善の解決策は、このメソッドをAppServiceProvideで呼び出すことです。

これは、この種の問題の最良の解決策です。私はこれを私のプロジェクトで使用しています。私の場合、2つの環境DevelopmentおよびProductionがあります。そのため、プロジェクトが開発モードの場合、ローカルサーバーまたはライブサーバーを検索します。したがって、ここでdynamic-DBコンセプトを設定できます。

関数を作成する必要がありますboot()Functionの内部でこれを呼び出す必要がありますApp\Providers\AppServiceProvide.php

    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;
}
0
pankaj kumar

別のデータベース接続を使用するつもりなら、それはドキュメントに存在します:

Schema::connection('foo')->create('users', function (Blueprint $table) {
    $table->bigIncrements('id');
});
0
A.Soliman

私はようやくこの混乱を理解したと思います...このソリューションは各テナントのデータベースの構成を必要とせず、一度だけ実行する必要があります。

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」という名前の接続があり、すべてのテナントのデータベース名が含まれています。テナントデータベースにもデフォルトの接続を設定しています。そのデータベースは、migrationsテーブルの処理を担当するデータベースです。

Foreachステートメントを使用すると、テナントデータベースを通過し、各データベースで移行を実行します。

デフォルトの接続では、すべてのテナントのデータベースにアクセスできるユーザーを構成して、それを機能させる必要があります。

0
JoeGalind

これは、どの移行がどのデータベースに対応するかを覚えるのは面倒です。

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');
}

すべての移行は、実行時に手動でデータベースを指定する必要がなく、自動的に実行できます。

移行テーブルはデフォルトのデータベース内に保存されていることに注意してください。

0
Tebe