php - How do I connect to different databases at run time? -
i making multi-tenant multi-database app has 1 central database , many sub-databases.
the app creates instance of organisation in central database, , each organisation creates sub-database different tables.
to achieve this, have made class class setup
- creates organisation
- creates database
- configures connection database , connects it
- runs proper migrations it.
all wrapped in constructor, upon caling setup::create of runs properly.
most of database configuration , connection inspiried tutorial.
to test whether logic goes wanted, interacted application via :
- tinker
- web browser.
to suprise, outcome different in both cases, , never wanted far connecting database concerned.
interaction tinker :
after creating calling setup::create , having output telling me went okay, try check myself database on right using:
db::connection()->getdatabasename() it outputs sub-database name have created organisation , connected to, logical , going accordingly.
however, attempt connect database creating new configuration , connecting db methods have provided, not work, still on sub-database on.
interacting browser :
this time, having setup::create wrapped in controller's code, attempt test again, made line in layout output me current database :
<?php echo db::connection()->getdatabasename() ?> at first, while still on central database, name appears, after calling setup::create, switches sub-database -which expected- then, after 1 refresh, on central database again -which totally unexpected-
so, happens here? , how connect of different databases how wish when wish?
extra:
testing in tinker, have went point have commented out migration code, , left creation of database , connection it. suprise, not connect database. started thinking migration code has connecting database, or maybe tinker has different behaviors ingore.
important:
- i have came across threads solutions using querybuilders mentioned
- please, not provide such answers because aim switch databases entirely point can use eloquent model's events no problem.
- by mean, want able use
model::createafter having connected database instead ofdb::connection()->....
- by mean, want able use
technical details:
i using laravel 5 mysql-server, on ubuntu machine.
i stumbled upon question , had answer.
i made class called databaseconnection:
class databaseconnection extends model { static $instances=array(); protected $database; protected $connection; public function __construct($options = null) { // set database $database = $options['database']; $this->database = $database; // figure out driver , default configuration driver $driver = isset($options['driver']) ? $options['driver'] : config::get("database.default"); $default = config::get("database.connections.$driver"); // loop through our default array , update options if have non-defaults foreach($default $item => $value) { $default[$item] = isset($options[$item]) ? $options[$item] : $default[$item]; } $capsule = new capsule; $capsule->addconnection($default); $capsule->seteventdispatcher(new dispatcher(new container)); $capsule->setasglobal(); $capsule->booteloquent(); // create connection $this->connection = $capsule->getconnection(); databaseconnection::$instances[] = $capsule; return $this->connection; } } so, whenever in controller manipulates tables of sub-database, go way:
public function randomactioninmycontroller() { $db_connection = new databaseconnection(['database' => 'name_of_db']); $somemodel = new model/model::find()..// return myreturnstuff; } extra bonus:
the use of static attribute $instances in databaseconnection boils down retrieving latest database connection ease uses.
for example, if ever wanted retrieve it, wrapped in function such
function currentorlatestdbconnection() { if( !empty(databaseconnection::$instances) ) { return end(databaseconnection::$instances)->getconnection()->getdatabasename(); } } notes :
if encounter errors such unknown class 'container' or capsule or of kind, make sure check question link have provided, , use use statements properly.
concerning upcoming answers :
it seems me database connection lives within the brackets of controller's action, when proceed action specifies no connection, returns central database automatically.
which has got me thinking there must way set database connection sub-database in 'global' way whole function, such middleware or something.
i love see answer, implementing such thing.
update :
i came neater way it.
i assume on same ground me, wanting change databases conditionally in accordance each controller... say, each of controllers requires different database, sake of argument.
what using solve `middlewares.
first, explain do..
we going check name of controller (and action) , set proper database wish set.
go command-line , type in:
php artisan make:middleware setdatabaseconnectionmiddleware
to create middleware ready boilerplate.
or, if hard way, go app_name/app/http/middleware , create 1 manually.
go helper methods file( if have one, if not, dude make one!)
function getcontrollerandactionname() { $action = app('request')->route()->getaction(); $controller = class_basename($action['controller']); list($controller, $action) = explode('@', $controller); return ['action' => $action, 'controller' => $controller]; }
this return array both action name , controller name, if want return restrictidly controller's name, feel free remove 'action' => $action code.
- inside of middleware, way :
namespace app\http\middleware; use closure; use databaseconnection; class setproperdatabase { /** * handle incoming request. * * @param \illuminate\http\request $request * @param \closure $next * @return mixed */ public function handle($request, closure $next) { $database_name = ''; $controllerandactionname = getcontrollerandactionname(); $controller_name = $controllerandactionname['controller']; $action_name = $controllerandactionname['action']; if($controller_name == 'my_controller_namecontroller') { $database_name = 'your_proper_database_name'; } else { $database_name = 'other_db'; } $database_connection = new databaseconnection(['database' => $database_name']); return $next($request); } } 4.now, have created middleware, let tell app find , under name.
- go app_name/app/http/kernel.php
in
$routemiddlewarevariable, add line'set_proper_database' => \app\http\middleware\setproperdatabase::class,
this way know how call it.
finally, setting up.
- go
controller.php(the abstract class of controller's inherit)
public function __construct(){$this->middleware('set_proper_database');}- go
and should you.
if have further questions, please feel free comment.
// resources :
3.further middleware documentation notes : i'd appreciate edition concerning styling , code indenting, since seems struggled style code in here in vain, indentions used had no effeft.
Comments
Post a Comment