laravel怎么动态切换数据库

我想在laravel中动态的切换数据库,
比如现在有两个数据库,db1db2,里面都有一张表articles
现在我想把db1articles的记录查询出来,写入 db2articles,

目前env文件中连接的是 db1:

DB_DATABASE=db1

尝试这样做:

    public function test()
    {
        $articles=Article::all();

        Config::set("database.connections.mysql", [
            "host" => "127.0.0.1",
            "database" => "db2",
            "username" => "root",
            "password" => ""
        ]);
        //DB::purge('mysql');  //有没有这一行,都会出现同样的error
        DB::table('articles')->insert($articles);
        dd('ok');
    }

运行上面的方法,出现如下错误:

Undefined index: driver

config/database.php文件中,相关设置项如下:

    'default' => env('DB_CONNECTION', 'mysql'),


    'connections' => [

        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],

    ],

因为有比较多数据库需要切换,所以不想去env文件中修改,也不想写死在config/database.php文件中。

所以问题就是应该怎么动态切换数据库呢?

阅读 17.4k
7 个回答

方法一:多配置实现

  • 配置文件照着新增一个配置:

    'default' => env('DB_CONNECTION', 'mysql'),


    'connections' => [

        'mysql_read' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],
        'mysql_write' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],

    ],
  • 使用 DB 门面连接不同数据库:

$articles = DB::connection('mysql_read')->select(...);
$update_res = DB::connection('mysql_read')->where(...)->update(...);
  • 也可以在模型中指定数据库连接:

public $connection = 'mysql_read';

方法二:使用 laravel 读写分离

  • database.php 配置文件:

'mysql' => [
    'read' => [
        'host' => '192.168.1.1'
    ],
    'write' => [
        'host' => '196.168.1.2'
    ],
    'driver'    => 'mysql',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
]
  • 设置完毕之后,Laravel5默认将select的语句让read指定的数据库执行,insert/update/delete则交给write指定的数据库,达到读写分离的作用。

参考:

新手上路,请多包涵

最近也遇到楼主类似的场景,基本上一个项目,就是一个数据库,如果写在配置文件里,会很累,
所以在中间件里要动态的切换数据库。

楼主的那种方式,应该是laravel4+左右的方式,laravel5+的不再是那种格式了

\Config::set('database.connections.mysql.host',$project_db_setting->host);
\Config::set('database.connections.mysql.port',$project_db_setting->port);
\Config::set('database.connections.mysql.database',$project_db_setting->database);
\Config::set('database.connections.mysql.username',$project_db_setting->username);
\Config::set('database.connections.mysql.password',$project_db_setting->password);

//下面这句很重要,要重连下数据库,要不然,连的还是原数据库
\DB::reconnect();

我的是laravel5.6的,测试成功了

没有你想像中的方法.

不管如何, 数据库连接总需要host, database, user, password, 你不放config里, 准备放哪呢?

直接写死到控制器里面么?

所以结果就是在database.php/connections里面增加配置,

要用配置的时候, 使用Model::on() 方法指定使用哪个连接.

新手上路,请多包涵

请问你是怎么做的,我现在是打算放到缓存中,然后再配置

新手上路,请多包涵

use IlluminateDatabaseCapsuleManager;
引入这个,里面东西自己看去

新手上路,请多包涵
Undefined index: driver

是因为你动态添加配置的数据中没用添加驱动类型,看数据库配置文件image

所以把你的代码小改一下就ok了

 public function test() {
        $articles=Article::all();

        \Config::set("database.connections.mysql", [
            'driver' => 'mysql',
            'port' => '3306',
            "host" => "127.0.0.1",
            "database" => "db2",
            "username" => "root",
            "password" => ""
        ]);
       $article =  DB::connection('mysql')->select('select * from articles');
       
        dd($article);
    }

另外不建议你覆盖原有的数据库配置,建议是新增数据库配置,
因为 config('database.connections.mysql') 这个配置数据是存在的,
新增的话 可以 Config::set("database.connections.mysql_1", [...])
然后在使用的时候 DB::connection('mysql_2')

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进