如何覆盖Laravel的数据库连接

时间:2014-11-15 19:53:43

标签: laravel laravel-4 eloquent

民间,

我现在已经尝试克服这个问题超过10个小时了,我决定在疯狂之前寻求帮助。

我想要实现的是某种多租户,我为每个客户提供专用数据库,并根据请求的发布者加载具体数据库。例如。如果客户A发送请求,则加载数据库A,如果B发送请求,则加载数据库B.我们有数千个客户,因此在databse.php文件中预定义的所有配置都不是一个选项。

在一些特殊情况下,无论发行人是谁,都应加载相同的数据库。例如。如果请求是X,则始终加载数据库C.

我有以下架构: BaseModel扩展了Eloquent模型。 扩展BaseModel的应用程序模型。 一些与应用程序模型对话的库。

由于我的所有数据库请求都通过BaseModel,我认为最好的解决方案是在BaseModel的构造函数中插入切换到正确数据库的代码。 E.g:

class BaseModel extends \Eloquent { 


public function __construct(array $attributes = array()) {     

    $currentConfigs = \Config::get('database.connections.customers');    

    $currentConfigs['database'] = 'db_A'; //this varies depending on the request
    $currentConfigs['prefix'] = 'custName'; //this varies depending on the request                               

    \Config::set('database.connections.customers', $currentConfigs); 

    parent::__construct($attributes);        
} 

我面临的问题是我似乎只能设置一次配置。换句话说,如果我在请求的整个生命周期中只需要数据库A或B,那么一切正常。但是,如果我需要切换到数据库C,这不起作用。 BaseModel继续在A或B中查找所需的表,即使我尝试显式加载C.看起来db设置是不可变的或类似的东西。

那就是说,我有几个问题:

  1. 动态加载不同数据库运行时的最佳方法是什么,记住一个请求可能需要查询多个数据库而不只是一个。

  2. 如何卸载或重置数据库连接,以便我设置一个新的?

  3. Laravel中的哪种方法可以为我提供有关当前数据库连接的信息?我需要调试方法,但我完全不知道可能的方法。

  4. 任何帮助/提示都将不胜感激。

1 个答案:

答案 0 :(得分:5)

问题是,Laravel使用配置建立连接,然后将其保存在内存中。如果要通过设置新的连接变量来执行此操作,则必须在进行更改后重新连接。 (另请注意,您可以使用令人敬畏的点符号直接设置配置)

\Config::set('database.connections.customers.database', 'db_A');
DB::reconnect('customers');

然而,在我看来,更好的方法是使用SQL来切换数据库

DB::unprepared('USE db_A');

要获取当前数据库名称,您也可以使用SQL

DB::select('SELECT DATABASE()')[0]->{"DATABASE()"} // DATABASE() might be something else if you're not using MySQL

更新 - 表格前缀

使表前缀动态化的简单方法是在BaseModel构造函数中添加它

$this->setTable('custName'.$this->getTable());