Application architecture for Codeigniter - multiple domain, single codebase, multiple databases
I've developed a website with the idea of using a single codebase for multiple sites each with their own DB. Currently one is live, with many (up to 100) to follow.
My question is about the ideal, best-practice way of managing this kind o开发者_高级运维f architecture (not necessarily the easiest or most realistic, but the ideal from which I can work back from).
For the codebase I have gone down the route of making the entire thing one install of codeigniter and associated code and all site related configuration is in a set of config files that pick up the host name and use that to define the site title, tracking code, css/js directories etc. This seems to be a good setup and I can see it working for a large number of sites of the same code.
For the databases, how would one manage multiple databases as the schema changes with development? Would you manually push changes to the databases as needed or use an automatic tool? There is a Rails like migrations plugin for Codeigniter here, that seems like it might be a good idea.
This article should show you exactly how to do it. It is really simple and works fine.
How to: Multi-site CodeIgniter Setup
If I understand you correctly you have multiple logical websites running off a single physical instance of the code, but each site has it's own database.
This is known as 'Multitenancy'; and you should be able to find plenty of architectural advice for this.
I haven't done a lot of this myself, and it's definitely non-trivial. It's a lot like security - you can't add it as an after-thought, if you want best practice you'll have to bake it into the design before you write a line of code.
It goes without saying that the code-base itself is only part of the overall solution: change management is going to be several orders of magnitude more difficult.
Sorry I can't offer more specific help.
I recently had a similar situation. I wanted to have several directories all running the same application but using different databases. Here's how I did it:
First I created some empty sub-directories. For this example we'll call them /subdir_1
, /subdir_2
and /subdir_3
.
Within each of these directories I made a copy of the CodeIgniter index.php file and placed it in each directory. My file structure now looks something like:
/application
/system
/subdir_1
index.php
/subdir_2
index.php
/subdir_3
index.php
This could also be accomplished with some .htaccess rules but that's a whole other story.
In each of the index.php files I've changed the $system_path
and $application_folder
variables to point to the /application
and /system
directories. For my particular case I changed my index.php file to:
/*
*---------------------------------------------------------------
* SYSTEM FOLDER NAME
*---------------------------------------------------------------
*
* This variable must contain the name of your "system" folder.
* Include the path if the folder is not in the same directory
* as this file.
*
*/
$system_path = "../system";
/*
*---------------------------------------------------------------
* APPLICATION FOLDER NAME
*---------------------------------------------------------------
*
* If you want this front controller to use a different "application"
* folder then the default one you can set its name here. The folder
* can also be renamed or relocated anywhere on your server. If
* you do, use a full server path. For more info please see the user guide:
* http://codeigniter.com/user_guide/general/managing_apps.html
*
* NO TRAILING SLASH!
*
*/
$application_folder = "../application";
At this point hitting any of the sub directories should display your application.
From here we need to set the base_href
for each directory. We'll do this with a simple change to the main /application/config/config.php
file. Replace the $config['base_url']
line in your /application/config/config.php
file with:
$uri = $_SERVER['REQUEST_URI'];
$pieces = explode('/', $uri);
if ($pieces[1] == 'index.php') {
$config['base_url'] = 'http://' . $_SERVER['HTTP_HOST'] . '/';
define('SITE', 'default');
} else {
$config['base_url'] = 'http://' . $_SERVER['HTTP_HOST'] . '/' . $pieces[1] . '/';
define('SITE', $pieces[1]);
}
The above snippet sets the $config['base_url']
to the appropriate sub directory (or the root directory if not in a sub-directory).
The define('SITE', $pieces[1])
line creates a constant we can access throughout our application to let us know which sub-directory we're in.
The final piece of the puzzle it so let our application know which database to use. In my case I wanted each sub-directory to use its own database. To do this we'll use the SITE
constant we created in the config.php
file.
In our /application/config/database.php
file we're going to add some alternate database settings. To do this we copy the [default]
database connection settings and setup alternate settings for each of our subdomains. Here's how one of my sets look:
$db['subdir_1']['hostname'] = "localhost";
$db['subdir_1']['username'] = "[USERNAME]";
$db['subdir_1']['password'] = "[PASSWORD]";
$db['subdir_1']['database'] = "[DATABASE]";
$db['subdir_1']['dbdriver'] = 'mysql';
$db['subdir_1']['dbprefix'] = '';
$db['subdir_1']['pconnect'] = TRUE;
$db['subdir_1']['db_debug'] = TRUE;
$db['subdir_1']['cache_on'] = FALSE;
$db['subdir_1']['cachedir'] = '';
$db['subdir_1']['char_set'] = 'utf8';
$db['subdir_1']['dbcollat'] = 'utf8_general_ci';
$db['subdir_1']['swap_pre'] = '';
$db['subdir_1']['autoinit'] = TRUE;
$db['subdir_1']['stricton'] = FALSE;
I have other sets for [subdir_2]
and [subdir_3]
. Now we need to tell our application which database settings to use. To do this we grab the SITE
constant, so the final line in our /application/config/database.php
file is:
$active_group = (defined('SITE') && array_key_exists(SITE, $db)) ? SITE : 'default';
The above line sets the active database settings group to match the sub directory.
And thats it :) Hopefully this helps someone.
精彩评论