Reputation: 233
Over the past couple of years I have developed a very customised PHP/MySQL application that is used for a number of clients. I have been creating a new database and new installation for each client up to this point.
The first obvious problem here is keeping multiple installations up to date with any code changes; a second problem is that each installation has a large amount of users; and for most clients; some of these users are the same - and they have to have a number of seperate user accounts and urls to remember.
I am moving the application over to Laravel 5 at the moment and looking into the best implementation for multi-tenancy; so looking for a little advice on the best implementation. I've used Laravel before but am by no means an expert.
This is what I am thinking as far as setup.
1 Master Database that holds tables for:
Then a seperate database for each installation that contains all the information that is needed for, and submitted to, that installation.
The ideal setup is that a user can go to a subdomain i.e installationname.appname.com; sign in with their master login details and automatically go to the required installation; OR go to appname.com, sign in and then select which installation to connect to.
My questions are:
I'm sure there's a lot of issues that I have not thought of; but if anyone has any links or guidance that may help that would be great. First time asking a question on SO but have found a huge amount of research help here in the past so thanks to the community!
UPDATE - So I think I have a way to make this work now; using seperate databases as above; set
protected $connection = 'tenant_connection'
in the models relating to tenant-specific database content.
Then somewhere in a header file set the tenant_connection that is wanted based on a session variable which has been set on login/by subdomain.
$tenant = Installation::where('installation', '=', $session['installation'])->first();
Config::set('database.connections.tenant_connection', array('driver' => 'mysql', 'host' => $tenant->db_hostname, 'username' => $tenant->db_username)... etc.
Assuming relationships will work across connections; I don't see why this would not work; just need to work out best place to set the tenant connection.
Upvotes: 16
Views: 8662
Reputation: 233
Ok so what I ended up doing was having all user info, names of installations and mappings of what users can access what installations in one database, and all tenant info in seperate databases.
I then had two connections, mysql and mysql_tenant; where mysql_tenant database is not pre-set but dynamic.
The User, Installations and mappings model use the mysql connection, all others use mysql_tenant
Created a code for each installation, and used this as the name of the tenant database; storing this code in the session.
Used a middleware MultiTenant, to control the switching between installations using these key lines:
$tenant_id = session()->get('tenant');
\Config::set('database.connections.mysql_tenant.database', $dbname);
\DB::setDefaultConnection('mysql_tenant');
There's a lot more to it for building the method to switch etc, but this is the gist.
Upvotes: 4
Reputation: 577
Laravel 5 is advanced enough that you should be able to have simply one installation along with a strategic database, with well defined relations and keys. There is rarely ever a need for multiple databases.
If you can be more specific about your requirements I can provide a more specific answer.
Upvotes: 0
Reputation: 60048
It is difficult to answer most of your question - as it is specific to your application and opinion based.
But the one bit I can answer is different models can have different database connections. So your user
model uses the normal default connection - but your other models can use another connection:
class Example extends Model {
protected $connection= 'second_db_connection';
}
Then in your DB connection file - you would have something like this:
return array(
'connections' => array(
'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database1',
'username' => 'user1',
'password' => 'pass1'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
'second_db_connection' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database2',
'username' => 'user2',
'password' => 'pass2'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
),
Upvotes: 3