【问题标题】:How to overwrite Laravel's database connection如何覆盖 Laravel 的数据库连接
【发布时间】:2015-01-13 00:39:16
【问题描述】:

伙计们,

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

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

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

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

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

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 中的哪种方法可以为我提供有关当前数据库连接的信息?我需要调试的方法,但我完全看不到可能的方法。

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

【问题讨论】:

标签: laravel laravel-4 eloquent


【解决方案1】:

问题是,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());

【讨论】:

  • 太棒了,我认为这是缺失部分的 95%。我真的很想接受你的回答,但似乎还有一个问题:(在 DB::reconnect 之后,表前缀似乎被忽略了。有什么想法吗?我之前没有提到过,就像我想的那样无关紧要,但我的一些表有前缀,而另一些则没有,我需要能够设置这些运行时的灵活性......
  • 嗯..也许在重新连接后尝试DB::setDefaultConnection('customers');。 (不知道为什么,但我在一个在线论坛上发现了)如果你使用USE db_A 方法呢?
  • setDefaultConnection 没有成功:(我会尝试使用 USE db_A 方法,但我想知道它是否会保留前缀......将尝试并在一段时间内更新主题。
  • 同理,前缀被忽略...目前唯一的解决方案是在我们进入 BaseModel 构造函数之前引入前缀。它不像我希望的那样干净,但除非有任何其他建议,否则我很可能最终会这样做......
  • 奇怪.. 我刚试了一下,一切正常。您确实已经在数据库配置中定义了前缀,不是吗?
猜你喜欢
  • 2016-03-23
  • 2011-10-29
  • 1970-01-01
  • 1970-01-01
  • 2019-05-05
  • 2016-04-15
  • 1970-01-01
  • 2013-09-07
  • 1970-01-01
相关资源
最近更新 更多