web-dev-qa-db-fra.com

Laravel: exécuter des migrations sur une autre base de données

Dans mon application, chaque utilisateur a sa propre base de données créée lors de son inscription. Les données de connexion et de base de données (nom de la base de données, nom d'utilisateur, mot de passe) sont enregistrées dans une table dans la base de données par défaut.

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

Maintenant, je veux exécuter quelques migrations sur la base de données d'un nouvel utilisateur après sa création.

C'est possible?

merci

17
Pooya Saberian

Dans votre app/config/database.php, vous devez:

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

Maintenant que vous avez préparé deux connexions à la base de données dans votre migration, vous pouvez effectuer:

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

Cela devrait fonctionner. Plus d'infos sur: http://fideloper.com/laravel-multiple-database-connections

35
pietrovismara

Si vous placez la configuration de la base de données sur le database.php fichier, cela peut vous aider:

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

J'ai en fait rencontré le même problème et la réponse de Joe n'a pas fonctionné dans mon cas, car j'ai différentes connexions à la base de données (donc hôte, port, utilisateur et passe différents).

Par conséquent, la migration doit effectuer de nombreuses reconnexions tout le temps:

  • La migration commence avec la base de données par défaut (dans mon cas, c'est client_1 )
  • Récupère les éléments de la table migrations et clients
  • Déconnectez la base de données par défaut
  • Se connecter à la base de données de client_2, exécuter les parties de migration, déconnecter client_2
  • Connectez-vous à nouveau à la base de données par défaut, stockez le journal de migration

Et puis bouclez-le pour chaque client.

    /**
     * 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);
        }
    }

Et la classe où la magie est stockée:

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,
        ]);
}

Avec cette solution, je peux exécuter exactement les mêmes migrations sur chaque client, mais la migration est simplement stockée dans client_1, mon type de client maître.

Attention toutefois aux deux DB::disconnect();. Cela va gâcher la situation sans ceux-ci car les journaux de migration sont stockés dans la base de données d'un autre client ou autre.

Ah et au fait, ClientController ne fait rien de spécial:

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

J'ai le même problème, ma solution est de changer la base de données en utilisant Config::set Puis d'exécuter Artisan::call("migrate"). en fonction de votre code:

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

la configuration n'a changé que sur votre session, puis réinitialisée plus tard en tant que paramètre actuel.

2

La meilleure solution est que vous pouvez appeler cette méthode sur AppServiceProvide

c'est la meilleure solution pour ce type de problème. J'utilise ceci dans mon projet. Dans mon cas, j'ai deux environnements Développement et Production. donc lorsque le projet est en mode développement, il se penchera sur le serveur local ou sur le serveur Live. Vous pouvez donc définir le concept dynamic-DB ici.

vous devez créer une fonction, puis vous devez l'appeler à l'intérieur de fonction boot () on App\Providers\AppServiceProvide.php

    public function boot()
    {
       DBConnection();

    }

J'ai créé Helper Fichier pour cela. donc mon code dans 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

Si vous entendez utiliser une connexion à une base de données différente, elle existe dans les documents:

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

Je pense que j'ai finalement compris ce gâchis ... Cette solution n'a pas besoin d'une configuration pour la base de données de chaque locataire et doit être exécutée une seule fois.

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

Où j'ai une connexion nommée "tenants" sur mon database.php, qui contient le nom de la base de données de tous mes locataires. J'ai également la connexion par défaut à ma base de données de locataires. Cette base de données est celle chargée de prendre en charge la table des migrations.

Avec l'instruction foreach, elle passe par les bases de données des locataires et exécute la migration sur chacune d'elles.

Sur votre connexion par défaut, vous devez configurer un utilisateur qui a accès à toutes les bases de données du locataire pour que cela fonctionne.

0
JoeGalind

Il est fastidieux de se rappeler quelle migration correspond à quelle base de données.

Pour Laravel 5.5 j'ai utilisé cette approche:

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

Toutes les migrations peuvent être exécutées automatiquement sans avoir à spécifier manuellement la base de données lors de leur exécution.

Veuillez noter que la table des migrations est stockée dans votre base de données par défaut.

0
Tebe