How to change database name before authentication in laravel 5.1 - php

I have multiple database. I want to change db name based on the url dynamically. How can I set particular db before authentication.
I want to change database from authentication to through out the application.
For ex.
If url is like lara.local.com/comapny1
then it will select database company1
If url is like lara.local.com/company2
then it will select database company2
Based on the selected database authentication will be done and selected database will be used for that user.

Make entry for second database in config/database.php
'company1' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'database1'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
'company2' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => 'database2',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
By default your queries will use the mysql connection to change connection to 'company1'
DB::connection('company1')->select($query);
Additionally you can set database connection for Model
$someModel = new MyModel;
$someModel->setConnection('company1');
You can use the Request::is() to get URI from URL
if(Request::is('company1')){
//change database to company1
Config::set("database.connections.company1.database", 'company1');
}
elseif(Request::is('company2'){
Config::set("database.connections.company1.database", 'company2');
}

You can achieve this thing with below steps:
1 Define multiple connection into database.php for example:
'db1' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'db1_connection',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
2 Use connection based on conditional statement(You should move this code else)
//Check url that contains 'MYCODE'
if ('URL Contains' == 'MYCODE') {
DB::disconnect();
Config::set('database.default','db1');
DB::reconnect();
}
else {
DB::disconnect();
Config::set('database.default','db2');
DB::reconnect();
}
It should work for you, however I haven't tested it. Reference taken from answer by Marcin Nabialek

You can do this in AppServiceProvider's boot() like this
public function boot()
{
if($this->app['request']->getHost()=='test.com') {
Config::set('database.default','mysql');
}
else{
Config::set('database.default','mysql1');
}
}

Related

How to dynamically create multiple database in laravel

I am creating Laravel 6.6 project,
my query is how to create new multiple databases in laravel and then how to handle it,
if I fetch data from the new database that I was recently created then how to register a new database in .env file dynamically?
I am doing this the following way.
I do have a dummy entry for my client connections in my config/database.php like this:
'clientDb' => [
'driver' => 'mysql',
'host' => env('DB_CLIENT_HOST', '127.0.0.1'),
'port' => env('DB_CLIENT_PORT', '3306'),
'database' => env('DB_CLIENT_DATABASE', 'some_default_client_name'),
'username' => env('DB_CLIENT_USERNAME', 'root'),
'password' => env('DB_CLIENT_PASSWORD', ''),
'unix_socket' => env('DB_CLIENT_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => false,
'engine' => null,
'dump' => [],
],
So, all my client-related models are used with $connection = 'clientDb';, the others using the default connection.
When changing a client (so i need to switch the connection), i just set the new connection by calling:
Config::set('database.connections.clientDb', [
'database' => NEW_DATABASE_NAME,
// all the other params from config
]);
After that, i figured out to call DB::reconnect('clientDb'); to get the connection really running.
I hope, this will lead you to the right direction 😉
You should usage from database.php in config directory. for example I have another mysql database which is different from main db:
so I add this code to database.php and connections section:
'mysql_second_db' => [
'driver' => 'mysql',
'host' => env('DB_HOST_SECOND_DB', '127.0.0.1'),
'port' => env('DB_PORT_SECOND_DB', '3306'),
'database' => env('DB_DATABASE_SECOND_DB', 'forge'),
'username' => env('DB_USERNAME_SECOND_DB', 'forge'),
'password' => env('DB_PASSWORD_SECOND_DB', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
],
You can use that:
$names=['name1','name2'];
Schema::create('t1', function($table)
{
$table->increments('id');
});
To set env look at that: ENV

Connect multiple databases dynamically in laravel [duplicate]

This question already has answers here:
How to use multiple databases in Laravel
(7 answers)
Closed 2 years ago.
I'm building an application which requires connecting 2 database. first one is static and another one is dynamic.
config/database.php is like
'mysql' =>
array (
'driver' => 'mysql',
'host' => '127.0.0.1',
'port' => '3306',
'database' => 'blog',
'username' => 'root',
'password' => '',
'unix_socket' => '',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => NULL,
),
'business2' =>
array (
'driver' => 'mysql',
'host' => '127.0.0.1',
'port' => '3306',
'database' => 'blog2',
'username' => 'root',
'password' => '',
'unix_socket' => '',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => NULL,
),
and model code is like
Class TableNewData extends Model
{
protected $connection = 'business3';
protected $table = 'table2_data';
public function getData()
{
return $this->get()->toArray();
}
}
I am able to connect multiple databases if I give static connection details but I am unable to connect database if I give dynamic connection details like
$connection = Session::get()->connection;
or
$connection=$_SESSION('connection');
What is the best way to connect multiple databases dynamically without effecting performance of application?
I had the same problem as you. This blog can definitely help you out.
The Ultimate Guide for Laravel Multi Tenant with Multi Database
Here is how the config/database.php file looks like based on your situation. Since the second one is dynamic, there is no need to define the database.
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'blog'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', 'password'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => 'InnoDB',
],
'business' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => '',
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', 'password'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => 'InnoDB',
],
Basically, set up a database helper function which connects to the database at runtime and then calls it in the right middleware.I just put the helper file at database/utilities/helpers.php
function connect($hostname, $username, $password, $database)
{
// Erase the tenant connection, thus making Laravel get the default values all over again.
DB::purge('business');
// Make sure to use the database name we want to establish a connection.
Config::set('database.connections.tenant.host', $hostname);
Config::set('database.connections.tenant.database', $database);
Config::set('database.connections.tenant.username', $username);
Config::set('database.connections.tenant.password', $password);
// Rearrange the connection data
DB::reconnect('business');
// Ping the database. This will throw an exception in case the database does not exists.
Schema::connection('tenant')->getConnection()->reconnect();
}
Don't forget to tell the composer that the helper function can be used globally by adding those line into the composer.json file.
"autoload": {
"classmap": [
"database"
],
"files":[
"database/utilities/helpers.php"
],
"psr-4": {
"App\\": "app/"
}
},
You also want to have static and dynamic models that should be extended to define which database connections to use.
class StaticModel extends Model
{
protected $connection = 'mysql';
}
class DynamicModel extends Model
{
protected $connection = 'business';
}
In the middleware set up the dynamic database connection according to the database name.
connect(getenv('DB_HOST'), getenv('DB_USERNAME'), getenv('DB_PASSWORD'), getenv('DB_SYMBOL') . $databasename);
Thus, you can use the model as normal but it has the dynamic database connections
One way of changing the connection at runtime is to set the values via the config:
config(['database.connections.mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'my_database'),
'username' => env('DB_USERNAME', 'my_user'),
'password' => env('DB_PASSWORD', 'my_password'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
]]);
This can be applied in a middleware to dynamically switch between tenant databases, for example.
You can also specify a connection via the DB facade:
DB::connection('mysql_2')->select(...);

Laravel 5.2 - Make different Read/Write Connections

In laravel 5.2, we wanted to have different connections for read/write, so I followed the advice as provided in laravel documents. But, by default, it was only creating default mysql named connection and not 2 different read/write connections, therefore it was picking the read connection for operations like INSERT/UPDATE.
After debugging, it was found that in DatabaseManager.php file the connection named passed as argument to makeconnection() was mysql and not mysql::read or mysql::write.
Before
config/database.php
'mysql' => [
//we need to have this nested options for both read/write
'read' => [
'host' => env('DB_READ_HOST'),
],
'write' => [
'host' => env('DB_WRITE_HOST'),
],
'host' => env('DB_READ_HOST'),
'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD'),
'driver' => 'mysql',
'database' => env('DB_DATABASE'),
'collation' => 'utf8_unicode_ci',
'port' => env('DB_PORT', '3306'),
'charset' => 'utf8',
'prefix' => '',
'strict' => false,
],
File - vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php
public function connection($name = null)
{
list($name, $type) = $this->parseConnectionName($name);
// If we haven't created this connection, we'll create it based on the config
// provided in the application. Once we've created the connections we will
// set the "fetch mode" for PDO which determines the query return types.
if (! isset($this->connections[$name])) {
$connection = $this->makeConnection($name);
$this->setPdoForType($connection, $type);
$this->connections[$name] = $this->prepare($connection);
}
return $this->connections[$name];
}
So, we have added a small change in the file, after adding this, it's now creating two different connections mysql.read/mysql.write and switching them appropriately according to the given sql operations SELECT,INSERT,UPDATE
Needed you feedback if this is a viable solution ?
After changing the file
config/database.php
'mysql' => [
//we need to have this nested options for both read/write
'read' => [
'host' => env('DB_READ_HOST'),
'username' => env('DB_READ_USERNAME'),
'password' => env('DB_READ_PASSWORD'),
'driver' => 'mysql',
'database' => env('DB_DATABASE'),
'collation' => 'utf8_unicode_ci',
'port' => env('DB_PORT', '3306'),
'charset' => 'utf8',
'prefix' => '',
'strict' => false,
],
'write' => [
'host' => env('DB_WRITE_HOST'),
'username' => env('DB_WRITE_USERNAME'),
'password' => env('DB_WRITE_PASSWORD'),
'driver' => 'mysql',
'database' => env('DB_DATABASE'),
'collation' => 'utf8_unicode_ci',
'port' => env('DB_PORT', '3306'),
'charset' => 'utf8',
'prefix' => '',
'strict' => false,
],
'host' => env('DB_READ_HOST'),
'username' => env('DB_READ_USERNAME'),
'password' => env('DB_READ_PASSWORD'),
'driver' => 'mysql',
'database' => env('DB_DATABASE'),
'collation' => 'utf8_unicode_ci',
'port' => env('DB_PORT', '3306'),
'charset' => 'utf8',
'prefix' => '',
'strict' => false,
],
File - vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php
public function connection($name = null)
{
list($name, $type) = $this->parseConnectionName($name);
// we check if the $type is read/write and store appropriate connections
if( $type != null ) {
$name .= '.' . $type;
}
//end
// If we haven't created this connection, we'll create it based on the config
// provided in the application. Once we've created the connections we will
// set the "fetch mode" for PDO which determines the query return types.
if (! isset($this->connections[$name])) {
$connection = $this->makeConnection($name);
$this->setPdoForType($connection, $type);
$this->connections[$name] = $this->prepare($connection);
}
return $this->connections[$name];
}

Laravel 5 Changing Database name in controller

ers. I need to change the database name into a specific controller. I already changed the database.php into this
'sqlsrv' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'loal'),
'database' => env('DB_DATABASE', 'test1'),
'username' => env('DB_USERNAME', ''),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
],
'sqlsrv2' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'local'),
'database' => env('DB_DATABASE', 'test2'),
'username' => env('DB_USERNAME', ''),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
],
My main DB is test1 and I need to change it into test2 db name in here :
public function TransactionHistory(Request $request){
Config::set('database.default','sqlsrv2');
dd(DB::connection() );
}
But it only returns null and it is still reading test 1. Anyone?
One way is to change the connection by using DB::connection() method:
$connection = DB::connection('sqlsrv2'); //this will create a database connection using sqlsrv2 in your config.
Now, you can use $connection to run the queries, etc.
Reference :
If you are using Eluquent there is more elegant way Database Connection
Create enother config for second connection
`
'connections' => array(
# Our primary database connection
'mysql' => array(
'driver' => 'mysql',
'host' => 'host1',
'database' => 'database1',
'username' => 'user1',
'password' => 'pass1'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
# Our secondary database connection
'mysql2' => array(
'driver' => 'mysql',
'host' => 'host2',
'database' => 'database2',
'username' => 'user2',
'password' => 'pass2'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
);
`
Set connection in your Model:
`
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The connection name for the model.
*
* #var string
*/
protected $connection = 'connection-name';
}

how to create a PHP file on the server with dynamic input

I am using Laravel and I created a multi-tenant app using the database connections, now I need to be able to create the contents of the database.php automatically with my chosen input.
Sample of database.php:
'connections' => [
'db1' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => 'db1',
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
],
'db2' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => 'db2',
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
]
]
So basically I will have a form that will ask those required fields like db name, connection name, password, etc. My problem is that I dont have a fixed amount of connections, could be one, two, four, w/e and file_put_contents() requires a string not an array of data. So my question is how to create this database.php file with the input from my form, create the opening and closing bracket and everything needed? Is there a function that will convert an Array to a String retaining the brackets and operators?
How can I achieve this?
If you want to go down on that road, make sure you have a template file, and you can setup placeholders that you simple replace.
Your sample template file would hold all requirements + placeholders for each info you need.
'db{index}' => [
...other key+values and it's placeholders...
],
And simply you can loop and concat as many times this block in your final database.php file.
on the other hand you could do this on the fly, some snippet to guide you.
$nameKey = 'NameOfConnection';
$dataSync = AtlasBases::find($id_client);
Config::set('database.connections.' . $nameKey, array(
'driver' => 'mysql',
'host' => $dataSync->site_db_server,
'database' => $dataSync->site_db_base,
'username' => $dataSync->site_db_user,
'password' => $dataSync->site_db_password,
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => '',
));
# And set the new connection to my models
$imobModel = new ImobImoveis;
$imobModel->setConnection($nameKey);

Categories