How to properly configured Multi-tenant in laravel? - laravel-5

I have created multi-tenant application, still now that working as expected.
Here is my sample code:
middleware :
public function handle($request, Closure $next)
{
$user = Auth::user();
if (! is_null($user)) {
Config::set('database.connections.tenant.host', $user->hostname);
Config::set('database.connections.tenant.database', $user->database);
Config::set('database.connections.tenant.username', $user->username);
Config::set('database.connections.tenant.password', $user->password);
}
return $next($request);
}
database.php :
'connections' => [
'main' => [
'driver' => env('DB_DRIVER', 'mysql'),
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', '123'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
'tenant' => [
'driver' => env('DB_DRIVER', 'mysql'),
'host' => '',
'port' => env('DB_PORT', '3306'),
'database' => '',
'username' => '',
'password' => '',
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
],
My doubt is : Above code is is possible to collapse DB connection, When multiple user access same time ? (each user has different DB)
for example :user A has school database and user B has college database
user A is try to logging [loading the page] that situation user B is login.
user B has no problem but user A -- get student details from college database or student database?

Related

Laravel Migration is not creating the table in different database

I have this migration file:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::connection('DB1')->create('feed_mappings', function (Blueprint $table) {
$table->bigIncrements('id_feed')->autoIncrement();
$table->string('id_project', 255);
$table->string('import_field_slug', 155);
$table->string('internal_field_slug', 155);
$table->tinyInteger('import');
$table->tinyInteger('custom_field')->default(0);
$table->dateTime('date_add');
$table->dateTime('date_upd');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('feed_mappings');
}
};
And I have this config in the database.php file:
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => 'InnoDB',
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'DB1' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '8889'),
'database' => env('DB_DATABASE', 'DB1'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', 'root'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => 'InnoDB',
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
Now, I have run this command :
php artisan migrate:refresh --seed
Now, All the migration file is creating a tables on default database but I want this feed_mappings should go to DB1 database.
BUT this feed_mapping is not going to DB1 database. Can you tell me why?
So the issue is in your database.php file where you are using the same variables for connections 1 and 2
'mysql' => [
'driver' => 'mysql',
***'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),***
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => 'InnoDB',
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'DB1' => [
'driver' => 'mysql',
**'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '8889'),
'database' => env('DB_DATABASE', 'DB1'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', 'root'),**
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => 'InnoDB',
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
what you need to do is create separate variables for db connections e.g:
DB_HOST // for connection 1
DB_HOST_2 // for connection 2
and use these in your config files for more info visit: https://codelapan.com/post/how-to-use-multiple-database-connections-in-laravel-8
config/database.php
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'mysql2' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST_2', '127.0.0.1'),
'port' => env('DB_PORT_2', '3306'),
'database' => env('DB_DATABASE_2', 'forge'),
'username' => env('DB_USERNAME_2', 'forge'),
'password' => env('DB_PASSWORD_2', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
Setup .env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_multiple_database1
DB_USERNAME=root
DB_PASSWORD=
DB_CONNECTION_2=mysql
DB_HOST_2=127.0.0.1
DB_PORT_2=3306
DB_DATABASE_2=laravel_multiple_database2
DB_USERNAME_2=root
DB_PASSWORD_2=
in Model example Post
protected $connection = 'mysql2';
in migration file
public function up()
{
Schema::connection('mysql2')->create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->timestamps();
});
}
public function down()
{
Schema::connection('mysql2')->dropIfExists('posts');
}

how do you request on a table with multi database

When i had one database i did :
$data=DB::table('data')->select(...)
How do I it with
$data=DB::connection('foo')->select(...);
Do it that way:
$data = DB::connection('foo')->table('data')->select(...);
Good luck!
You can just configure your as many database you want in config/database.php file,
'custom_db1' => [
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => false,
'engine' => null,
]
And Use it in eloquent Model like
protected $table = "custom_db1.table1";

How to change table prefix when a user logs in to account?

I am in new laravel, In my application When a user logs into his account I want to change the default database prefix from the env file. I setup wildcard subdomain for every users. When every user logs in I want to change the database prefix according to the sub domain.
So is it possible to change the laravel prefix globally if a user logs in Laravel?. Please suggest me if there is any solution. Thanks is advance.
Of course you can:
config/database.php
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
'mysql_earth' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_EARTH_DATABASE', 'earth'),
'username' => env('DB_EARTH_USERNAME', 'earth'),
'password' => env('DB_EARTH_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
'mysql_moon' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_MOON_DATABASE', 'moon'),
'username' => env('DB_MOON_USERNAME', 'moon'),
'password' => env('DB_MOON_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=forge
DB_USERNAME=forge
DB_PASSWORD=forgepw
DB_EARTH_DATABASE=earth
DB_EARTH_USERNAME=erth
DB_EARTH_PASSWORD=earthpw
DB_MOON_DATABASE=moon
DB_MOON_USERNAME=moon
DB_MOON_PASSWORD=moonpw
Use in your Controller example put your conditions on the connection and then you can have the query in each database:
$db = \DB::connection('mysql');
$db = \DB::connection('mysql_earth');
$db = \DB::connection('mysql_moon');
$products = $db->table('products')
->distinct()
->select("*" )
->orderBy('products.id','asc')
->get();

Laravel - Using multi connection in single query

I have use multiple database in my project. But is that possible to use multiple connection in single query in laravel? This is my connection config.
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => false,
'engine' => null,
],
'mysql_pdd' => [
'driver' => 'mysql',
'host' => env('DB_PDD_HOST', '127.0.0.1'),
'port' => env('DB_PDD_PORT', '3306'),
'database' => env('DB_PDD_DATABASE', 'forge'),
'username' => env('DB_PDD_USERNAME', 'forge'),
'password' => env('DB_PDD_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => false,
'engine' => null,
],
I want to join a tabel in my mysql connection to mysql_pdd table. Is that possible?
Yes, you can but for that you need to put condition, when you want to connect 'mysql' and when 'msql_pdd'.
if (mysql_connection){
$mysql =DB:: reconnect('mysql');
}else if(mysql_pdd_connection){
$mysql_pdd =DB:: reconnect('mysql_pdd');
}
Using $mysql & $mysql_pdd you can perform joins as well by code not by query.

Laravel - How to add new connection to database.php

I need to use several databases in laravel, and i'm trying to create a form to add a new db connection to connections array in config/database.php.
I don't want to add connections manually, but throught a form.
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '',
],
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
'pgsql' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
'sslmode' => 'prefer',
],
],
Thanks
You simple add as many databases to the array as you require then add the connection values to you .env file or to the array valyes like so:
return array(
'default' => 'my_first_db',
'connections' => array(
# Our primary database connection
'my_first_db' => array(
'driver' => 'mysql',
'host' => 'host1',
'database' => 'database1',
'username' => 'user1',
'password' => 'pass1'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
# Our secondary database connection
'my_second_db' => array(
'driver' => 'mysql',
'host' => 'host2',
'database' => 'database2',
'username' => 'user2',
'password' => 'pass2'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
),
);
Schema::connection('my_second_db')->create('a_new_table', function($table)
{
$table->increments('id'):
});
$users = DB::connection('my_second_db')->select('users');
To add connections through a form you would need to post the data to a template similar to the above and then write to the server, This is a bit of a security risk doing that and would need to be carefull in what you do and how you go about doing it, Posting database data in a request and then just saving the database data to a file is a bit overboard.
You could either setup a config file that has 10 databases pre-defined with PDO and then you could overwrite the settings or save to one of the config files that have no settings assigned.
You can use the config helper and set the config dynamically:
config([
'database.connections.mysql.database' => $dynamicDB,
'database.connections.mysql.username' => $dbUsername,
'database.connections.mysql.password' => $dbPassword,
// Any other dynamically set variables
]);
You could store the parameters in the session and default them to your config file:
config([
'database.connections.mysql.database' => session('db_database', config('database.connections.mysql.database')),
'database.connections.mysql.username' => session('db_username', config('database.connections.mysql.username')),
'database.connections.mysql.password' => session('db_password', config('database.connections.mysql.password')),
// Any other dynamically set variables
]);
Doing this in middleware would give you a little more control over where/when these parameters are being set and used.

Resources