2016-11-11 73 views
1

我在database.php中如下配置:Laravel 4 equolent - 如何动态更改默认数据库?

'connections' => array(

    'sqlite' => array(
     'driver' => 'sqlite', 
     'database' => __DIR__.'/../database/production.sqlite', 
     'prefix' => '', 
    ), 

    'mysql-primary' => array(
     'driver' => 'mysql', 
     'host'  => 'host1', 
     'port'  => '3306', 
     'database' => 'test', 
     'username' => 'root', 
     'password' => '', 
     'charset' => 'utf8', 
     'collation' => 'utf8_unicode_ci', 
     'prefix' => '', 
    ), 

    'mysql-slave' => array(
     'driver' => 'mysql', 
     'host'  => 'host2', 
     'port'  => '3306', 
     'database' => 'test', 
     'username' => 'root', 
     'password' => '', 
     'charset' => 'utf8', 
     'collation' => 'utf8_unicode_ci', 
     'prefix' => '', 
    ), 

    'default' => 'mysql-primary', 
) 

我想什么来实现从主DB切换到从DB中不可用的情况下比方说,用户尝试登录:

$user = User::where('username', '=', $username)->first(); 

我想在这里,如果有PDOException(这是应该在不可用的情况下,抛出)切换默认数据库并重试操作。我知道它可能在用户模型中,但我想切换到所有模型。

我都没有成功尝试:

App::error(function(PDOException $exception) 
{ 
    Log::error("Error connecting to database: ".$exception->getMessage()); 
    DB::setDefaultConnection('mysql-slave'); 
}); 

在filters.php

'default' => getDatabase() 


function getDatabase() 
{ 
    try{ 
    DB::connection('mysql-master')->getDatabaseName(); 
    }catch(PDOException $e){ 
    return 'mysql-slave'; 
    } 
    return 'mysql-master'; 
} 

在database.php中

两个不工作。 Laravel 4中有这种行为吗?

回答

1

简短的回答是:你不能使用外墙(DB :: etc)来做到这一点。

为什么?外观使用内部单例实例,该实例在第一次访问外观时被初始化。如果深入研究Laravel代码,您会发现,在包括DB服务提供者的服务提供者的引导程序/注册函数中,存在以单例创建的内部DB对象。该对象属于Illuminate \ Database \ Connectors \ ConnectionFactory类,并具有一个预先初始化的内部PDO对象,该对象通过存储在配置变量中的配置创建。

较长的答案是您可以使用类似于数据库服务提供程序中的引导代码的代码创建一个或多个您自己的Illuminate \ Database \ Connectors \ ConnectionFactory类的对象。我建议您仔细阅读引导程序代码并熟悉它,并且可以在此处找到代码和文档:https://laravel.com/api/4.2/Illuminate/Database/DatabaseServiceProvider.html

可能还有其他解决方法,包括提供额外的Illuminate连接器\ Database \ Connection(所有这些都可以像配置一样在配置中设置)连接到ConnectionFactory。这将涉及扩展现有的ConnectionFactory类,并将DB服务提供者更改为使用您自己的扩展而不是Laravel本机类。然后,您可以让ConnectionFactory提供一个内置故障转移的连接。它相当复杂但可能 - 我已经为ViewFactory类完成了它,但从未为ConnectionFactory类完成过。

对不起,这不是一个简单的HOWTO来回答你的问题,但它让你知道为什么这不起作用,只是你给的例子。例如,使用MySQL代理或负载平衡服务可能比较简单,例如,它可以自动检测哪个服务器正在运行并向其发送请求。