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 migrate
和 php 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) 从表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 中。
不过,注意两个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
它是此类问题的最佳解决方案。我在我的项目中使用它。就我而言,我有两个环境 Development 和 Production。因此,当项目处于开发模式时,它将在本地服务器上查看其他实时服务器。所以你可以在这里设置dynamic-DB概念。
您必须创建一个函数,然后您必须在 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;
【讨论】:
这不仅适用于迁移,而且适用于任何地方。以上是关于Laravel:在另一个数据库上运行迁移的主要内容,如果未能解决你的问题,请参考以下文章
MySQL数据库的Laravel迁移“无法添加外键约束”错误
带有 Sqlite 错误的 Laravel 迁移:typeSet 不存在