How to overwrite Laravel's database connection

*爱你&永不变心* 提交于 2019-12-13 00:42:30

问题


Folks,

I've been trying to overcome this issue for more than 10 hours now and I've decided to look for help before going insane.

What I'm trying to achieve is some sort multi-tenancy where I have a dedicated database for each customer and depending on the issuer of the request the concrete database should be loaded. E.g. if customer A sends a request, load database A, if B sends the request, load database B. We have thousands of customers, so having all configs predefined in the databse.php file is not an option.

In a few special cases, the same database should be loaded irrespective of the issuer. E.g. if the request is X, always load database C.

I have the following architecture: BaseModel which Extends Eloquent Model. Application models which extend BaseModel. A few libraries which talk to the Application models.

Since all my database requests go through BaseModel, the best solution that I thought would work was to insert the code which switches to the correct database in the BaseModel's constructor. 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);        
} 

The problem that I am facing is that I seem to be able to set the configs only once. In other words, if I only need database A or B throughout the lifecycle of the request, all works fine. Though, if I need to switch to database C, this doesn't work. BaseModel continues to look for the required tables in A or B, even though I tried to explicitly load C. It looks as if the db settings are immutable or something like that.

That said, I have a few questions:

  1. What is the best way to dynamically load different databases run-time, having in mind that one request may need to query multiple databases and not just one.

  2. How can I unload or reset the database connection, so that I set a new one?

  3. Which method in Laravel can give me information about the current db connection? I need ways to debug this, but I'm totally blind to the possible ways to go about that.

Any help/tips would be appreciated.


回答1:


The problem is, that Laravel establishes a connection using the config and then keeps it in memory. If you want to do it by setting new connection variables, you have to reconnect after making changes. (also note that you can set the config directly with the awesome dot notation)

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

However the better way, in my opinion, is to just use SQL to switch the database

DB::unprepared('USE db_A');

To get the current database name you can use SQL as well

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

Update - Table prefix

An easy way to make the table prefix dynamic too, would be to add this in your BaseModel constructor

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


来源:https://stackoverflow.com/questions/26950029/how-to-overwrite-laravels-database-connection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!