Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 4: Multiple Tenant Application, each tenant it's own database and one global database

Currently i have a application that hosts multiple tenants written in CodeIgniter. But i am really loving Laravel 4 and i would like to start migrating the application to Laravel.

Here is the current setup:

  • Each tenant has it's own database.
  • There is just one set of application files.
  • When we create a new tenant a new database is created and an install script is run and the database is seeded with some initial information.
  • Each tenant also has it's own subdomain. That is how we can detect which database to use.
  • There is a main database that holds tenant information and users and some other general tables.
  • When a schema update is needed we just create an update script that will run for each tenant. This happens via a specially coded CLI script for Codeigniter

In Codeigniter it's relatively easy to start and end new database connections.

With Laravel i have the following issues/questions.

  • How would you start/end database connections on the fly?
  • I would like to use Migrations but i would like to run them for each tenant. Migrations currently only run on the "main" database connection. And it only runs once.
  • Same goes for seeding..

These are my main issues, i have some other minor stuff but those can be worked around.

Hopefully someone can shed some light..

like image 486
Victor Gutierrez Avatar asked Jan 25 '13 14:01

Victor Gutierrez


2 Answers

I'm just taking a stab at this, so be warned :) The DatabaseManager class, which is used whenever you call DB, has and extend method. Here's the link to the source. The DB::connection() method should return an instance of Illuminate\Database\Connection. From all this, I would create a new user connection as follows:

$user = Auth::user(); DB::extend($user->username, function() use ($user) {    // $pdo = new PDO(); set this up how you see fit     return new Illuminate\Database\Connection($pdo, $user->databaseName, $tablePrefix); }); 

Personally, I would add a new method to each user, User::databaseConnection(), and call that when I extend the DatabaseManager.

DB::extend($user->username, function() use ($user) {     return $user->databaseConnection(); }); 

Through out your application you should be able to call a registered user's connection via:

DB::connection(Auth::user()->username); 

Update

Depending on how often and when you'd be calling the tenant connection, you may want to use the IOC container.

App::bind('tenantDB', function() {      return DB::connection(Auth::user()->username); });  App::make('tenantDB')->insert(...); 

I forgot about migrations and seeding. For migrations, you can set the file path

php artisan migrate:make foo --path=app/migrations 

So if you use the Config class to set the default database or DB::setDefaultConnection($username), I'd assume all migrations and seeding will be done for the current connection. When that process if complete you can switch back to you main database.

Update 2

The laravel developers are amazing and I should have definitely got the urge to check this out sooner than later. You can do migrations and seed on any database connection you've created.

artisan migrate --database='userConnectionName'  artisan db:seed --database='userConnectionName' 

Looking at Barry's answer, that is probably a good deal simpler than extending the DatabaseManager.

If you want to see all the options for these commands just run:

artisan help migrate artisan help db:seed 
like image 198
Blessing Avatar answered Sep 21 '22 06:09

Blessing


You can create 1 database with the tenant database credentials, and dynamically set them in your app:

$tenant = Tenant::where('username', '=', $username)->first(); Config::set('database.connections.tenant.username', $tenant->db_username); Config::set('database.connections.tenant.password', $tenant->db_password); Config::set('database.connections.tenant.database', $tenant->db_database); 

This will require to create 2 connections in your database.php file. (for instance app and tenant) and specify in your model which database to use (1 for the storing of tenants, 1 for the tenant specific database)

And probably create a route/script to create/update the tables. Not sure about migrations with multiple databases.

like image 45
Barryvdh Avatar answered Sep 25 '22 06:09

Barryvdh