Change the Database Connection Dynamically in Laravel [duplicate] - php

This question already has answers here:
Laravel: connect to databases dynamically
(8 answers)
Closed 3 years ago.
I have the master database with login table and corresponding database settings for each user. On login I should dynamically change the db settings fetching from the table.
I can change the db connection but this is not persisting.
Config::set("database.connections.mysql", [
'driver' => 'mysql',
"host" => $usr_host,
"database" => $usr_database,
"username" => $usr_username,
"password" => $usr_password,
...
]);
edit:
New database is created for each user when he/she registers with the app and thus i dont have the database connection for each user defined in the config/database.php

This way you can set new parameter when it comes to database:
\Config::set('database.connections.mysql.database', $schemaName);
Remember about PURGE to persist this settings
DB::purge('mysql');
Cheers!

Well you can use the default database for user login and have a new field for the database name. Then whenever you need to query a different database, you can just change your db connection.
Something like this
$someModel = new SomeModel;
$databaseName = "mysql2"; // Dynamically get this value from db
$someModel->setConnection($databaseName);
$something = $someModel->find(1);
You can read more about it here.
http://fideloper.com/laravel-multiple-database-connections

you need to get the config first.. then alter the specific field then set it back..
$config = Config::get('database.connections.company');
$config['database'] = "company_tenant_$id";
$config['password'] = "test2123";
config()->set('database.connections.company', $config);

I think a good place to change the database connection place is in bootstrap/app.php file, use the code below:
$app->afterBootstrapping(\Illuminate\Foundation\Bootstrap\LoadConfiguration::class, function ($ap) {
// your database connection change may happens here
});
It is before ServiceProvider register and boot, so even if you use DB or Eloquent staff in ServiceProvider, it works very well.

In laravel what you can do is create the different connections in the connections array of the file conf/database, then these connections you can use them when you are going to carry out operations in your application.
If you use query builder or raw expresions you must use the connection ('name') method to perform queries, for example:
$users = DB::connection('mysql')
->table('users')
->select(...)
->get();
If you use eloquent you can specify the name of the connection in the model file in the connection attribute, for example:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The connection name for the model.
*
* #var string
*/
protected $connection = 'mysql';
}
A solution to your problem could be that you have created the different types of connections according to the users in the file conf/database, and save the name of the connection that the user uses as a column in the user table, and when you go to make the queries you get the name of the connection of the user, for example:
$user = User::find(Auth::id());
$connection = $user->connection;
$users = DB::connection($connection)
                      ->table('users')
                      ->select(...)
                      ->get ();
more info:
https://laravel.com/docs/5.5/eloquent#eloquent-model-conventions
https://laravel.com/docs/5.5/database#read-and-write-connections

After an extensive search I found it this way:
Go to this file vendor\laravel\framework\src\Illuminate\Auth\Middleware\Authenticate.php
Go to the method: protected function authenticate($request, array $guards)
and right after the method has started, paste the following code:
if(auth()->check() && !empty( auth()->user()->db_name )){
$dynamic_db_name = auth()->user()->db_name;
$config = \Config::get('database.connections.mysql');
$config['database'] = $dynamic_db_name;
$config['password'] = "Your DB Password";
config()->set('database.connections.mysql', $config);
\DB::purge('mysql');
}
first we are checking if the user is logged in with
auth()->check()
Then as you may have added db_name name or the like column table to your users table according to each user. So in the next condition, I am making sure that the db_name is available:
&& !empty( auth()->user()->db_name )
Then after execution enters the if condition I get the db_name from the user record and set the configuration according to the user database, save the config and use purge method of DB class to persist this setting.
I was really stuck with it. I did not wanted to change my db connection in every class. So this is how I got it. Now I can use both Eloquent and DB without any tension anywhere. In my application I have one centeral database for login of all users and then for each organization there is a different database. So after the user has logged in, I do not need the centeral database (login database), I juse need the user/organization specific database. So this is how I got it to work.

Related

Changing database connection using Constructor for one user without effecting other users (Laravel)

I'm trying to change database connection for specific users, but the question will this affect other users?
For example, I added this Constructor to a Comment model
public function __construct(array $attributes = [])
{
if (Session::get('database') == 'new'){
$this->setConnection('newMysql');
}
parent::__construct($attributes);
}
If I have like 2000 users connected at the same time
Will this affect all queries for that comment model for one user with session = 'new' or it might affect other users as well?
Because from my understating, Constructor used for initialization and changing database connection might affect other users if they are using the comment model at the same time
Please correct me if I'm wrong.

Is there any way to connect to multiple dynamic databases in controller side using cakephp 3.7?

We are using a connection manager to do the process but we are unable to achieve the thing that we needed. we tried different ways to unable to connect to dynamic multiple databases. below is the code which we are using.
php 5.6 above with cakephp 3.7 versions.
use Cake\Controller\Component;
use Cake\ORM\TableRegistry;
use Cake\Datasource\ConnectionManager;
use Cake\Database\Connection;
use Cake\Database\Driver\Mysql;
public function setDatabase($company_id, $datasource = 'default') {
$dbConf = ConnectionManager::getConfig($datasource); //Here connect to dynamic database.
$dbConf['database'] = "db_".$company_id;//changing database name to which we need to connect with same configurations
$dbConf['name'] = "company";
$dbConf['encoding'] = 'utf8';
ConnectionManager::setConfig('company', $dbConf );
// ConnectionManager::config('company', $dbConf );
$JobSeekers = TableRegistry::get('JobSeekers');
$JobSeekers_details = $JobSeekers->find('all'); // firing query jobseekers table but still it's excueting in default db instead of company db.which trows error
$JobSeekers_data = $JobSeekers_details->first();
pr($JobSeekers_data);
}
What we need is jobseeker query must be execute in company level database but we are getting following error which says connection still in default db.
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'default_db.job_seekers' doesn't exist

CakePHP 3 - use multiple database connections *without ORM*

I have a CakePHP 3.4.6 web application. Due to the fact it's working with legacy (not written in Cake convention) database tables, we have opted to hand-code all of our SQL queries rather than trying to set up Table and Entity classes. I realise some people will disagree with this, but that's not the point of the question.
I have 3 databases: app_db, users_db, extra_db.
I've configured connections to each one in config/app.php such that:
'Datasources' => [
'default' => [], // 'app_db' credentials
'users_db' => [], // 'users_db' credentials
'extra_db' => [], // 'extra_db' credentials
];
I have a custom Model file located at src/Model/MyModel.php. An example of it being used to do a query on one of the databases (app_db) works like this:
namespace App\Model;
use Cake\Datasource\ConnectionManager;
class MyModel
{
protected $connection;
public function __construct()
{
$this->connection = ConnectionManager::get('default');
}
public function getData()
{
$sql = ''; // some SQL query
$stmt = $this->connection->prepare($sql);
$stmt->execute();
return $stmt->fetchAll('assoc');
}
}
This works because it gets the connection for default which maps to app_db.
But, I now want to run a query which needs to get data from app_db and JOIN with data from users_db.
How do I configure this in the Model so that the SQL will communicate with the other databases?
Simple way would be, to have another method, which will change connection.
public function switchConnection($connection=''){
$this->connection = ConnectionManager::get(connection);
}
end call it for change connection
MyModel->switchConnection('app_db');
next time you run getData, it will communicate with app_db instead of default.

how can i use database connection of the already connected database in codeigniter?

I have already database connected in config folder database.php file.
Is there any variable that can simply refers to that MySQLi connection, so that i can use the connection and do manual insertion like-
mysqli_query($alreadyconn, "insert into table ...");
insert() in Codeigniter.com
I know how to insert in codeigniter but i need the above specific case. and here i can not reconnect that database and use the variable.
Any Help Much Appreciated !
Use $this->db to refer to your db connection
$query = $this->db->query("
YOUR QUERY HERE
");
Ok. Seems you know about database.php. Will get know some more
$db['default'] = array(
'dsn' => '',
'hostname' => 'localhost', # host
'username' => '', # Username
'password' => '', # password
'database' => '', # Databse name
'dbdriver' => 'mysqli', # this can be MySQL or MySQLi
Note: Recommend to use MySQLi as db driver.
How to connect database??
There are Three ways to archive this
Gobally - (path - application/config/autoload.php)
$autoload['libraries'] = array('database');
Within the class only.
class ClassName extends CI_Model
{
public function __construct()
{
parent::__construct();
$this->load->database();
}
}
Can use in all the methods added within this class
Withing Methods only. (Mostly on controllers only)
class ClassName extends CI_Controller {
public function __construct()
{
parent::__construct();
}
public function index()
{
$this->load->database();
}
Can use inside the class only
What is Query Builder (3.0+) or Active Records(3.0-) ??
This pattern allows information to be retrieved, inserted, and updated in your database with minimal scripting. In some cases only one or two lines of code are necessary to perform a database action. CodeIgniter does not require that each database table be its own class file. It instead provides a more simplified interface.
How to query with the database & (Query Builder or Active Records) ??
First Load DB in autoload.php mention above(personally recommended).
Where ever you are in model or controller just use $this->db to get open connection with your DB.
With that you can add Query Builder methods like mention in the codeigniter docs. if you are like to use traditional SQL method, you feel free to use query() (Which is my favorite).
Example
$this->db->query("SELECT * FROM user WHERE name = 'Sparatn' AND ... OR... ");
But this not enough to produce meaningful data. So you have to follow these steps as well
$query = $this->db->query("SELECT * FROM user WHERE name = 'Sparatn' "); # 1
$result = $query->result_array(); # 2
return $result; #3
In #1 assign the database row data to an variable.
In #2 Convert the #1 to objective array(result_array objective array represent by this).
In #3 return the result to controller.
To Insert Data In Database you must do not need MySQL function in code igniter .
You should have to use
$this->db->insert()
function to store data in database .
For More Help kindly visit
https://www.formget.com/insert-data-into-database-using-codeigniter/
Thank You
None really answered to the question. The question is clear: how to recycle the codeigniter database connection to be used with a native mysqli_query function without using mysqli_connect again.
The upvoted answers above aren't helpful by any means to the issuer's question.
Use $this->db->conn_id as database connection reference in your $alreadyconn variable.

Copy a model to another database in symfony 1.4

Using Symfony 1.4 and doctrine I'd like to save a retrieved model to a different database connection:
retrieve model from master-database
change database connection to slave-database
save the model to the slave-database
I have the 2 connections defined in databases.yml.
here in pseudo-code:
$model = [retrieved from master-database];
$slaveConnection = Doctrine_Manager::getInstance()
->getConnection('slave-connection');
$model->save($slaveConnection);
If I create a new model, $model=new model(); the "code" above successfully saves the model to the slave-connection.
What is going wrong?
According to the Symfony log, Symfony recognizes the model as existing and issues an update (instead of an insert).
UPDATE model SET updated_at = '2011-10-21 17:37:32' WHERE id = '1';
Although Symfony is using the correct database connection ('slave-connection'), the update fails because the model isn't present in the slave-database, yet.
And the insert into the slave-database should use all values of the model, not only the changed ones, too.
Anyone can point me to the right direction to save an existing model to a different database?
edit with my solution.
Thanks samura!
Just some additions:
After performing deep copy Symfony saved a new id. But I wanted to really clone the model object to the slave db and so, I had to modify the id.
That caused unique constraint exceptions, so I had to delete first. So this is it:
$id = $model->getId();
$slaveConnection->execute("delete from modeltable where id=".$id);
$model_copy = $model->copy(true); # deep copy
$model_copy->setId($id);
$model_copy->save($slaveConnection);
hope this helps if someone else stumbles.
You could use the public function copy($deep = false) method of the Doctrine_Record class.
$model = [retrieved from master-database];
$slaveConnection = Doctrine_Manager::getInstance()
->getConnection('slave-connection');
$model_copy = $model->copy(true); # deep copy
$model_copy->save($slaveConnection);

Categories