Dynamic database switching

Some might remember my old post about development vs. productive setup.
It was mainly about how to switch dynamically based on the current environment. This can be useful if you want to have a single DB config file which will be distributed/uploaded to all environments. In my case: synced via shell script.

Since then I rewrote it quite often and it is now published in my Setup plugin (in /Lib).
It now has some more useful goodies. The config file can be kept more DRY (Don’t Repeat Yourself) and does allow automatic test config.

The most important new feature is the automatic environment awareness in CLI mode (using path).

Basic usage

Install the plugin in your Plugin folder first.

Your database.php then uses the class this way:

App::uses('BaseConfig', 'Setup.Lib');

class DATABASE_CONFIG extends BaseConfig {

    public $default = array(
        'environment' => array('localhost', 'domain'), // define the environments - optional
        'path' => array('/some/path/to/app/'), // define the paths - optional
        'datasource' => 'Database/Mysql',
        'persistent' => false,
        'host' => 'localhost',
        'login' => 'root',
        'password' => '',
        'database' => 'table_name',
        'prefix' => 'app_', //optional (I like to use prefixes, though)
        'encoding' => 'utf8'
    );

Actually, using the BaseConfig class you can cut it down to:

public $default = array(
    'environment' => array('localhost', 'domain'),
    'path' => array('/some/path/to/app/'),
    'datasource' => 'Database/Mysql',
    'host' => 'localhost',
    'login' => 'root',
    'password' => '',
    'database' => 'my_app',
    'prefix' => 'app_'
);

encoding defaults to utf8 and persistent defaults to false.

Both environment and path are used to determine the correct config.
The first dynamically selects the correct config based on the $_SERVER['HTTP_HOST'] setting and therefore the domain you are running the application with.
The latter does the same on CLI (Command Line Interface) – using the cake console. There we have to domain and therefore need the paths to find the correct configuration. If you use the shell only locally then you can skip setting the paths, of course.

Test config

That is probably the most useful goodie. You don’t have to take care of this anymore. It will also ensure that your "live" tables will not get touched, modified, overwritten etc.

If you only defined the default config yet, the BaseConfig class will automatically set the test config to the same database, but with a different prefix (defaults to zzz_).
You can overwrite the defaults very easy, though:

public $test = array(
    'database' => 'my_app_test',
    'merge' => true,
    'prefix' => 'app_',
);

In this case we force the merge with our default config and define an own database table as well as the same prefix to completely replicate the default settins on a secondary test evironment. All other config values will be automatically merged.

Manuel fixation

You can also manually enforce a certain DB config in your bootstrap or config.php file:

Configure::write('Environment.name', 'stage');
//or
$config['Environment'] = array(
    'name' => 'stage'
);

This will make the class use the $stage config (needs to be available then, of course).

Example

So for 3 environments, lets call them development, stage and live, we can easily define them like so:

public $default = array(
    'environment' => array('localhost', 'local.domain'),
    'path' => array('/some/path/to/app/'),
    'datasource' => 'Database/Mysql',
    'host' => 'localhost',
    'login' => 'root',
    'password' => '',
    'database' => 'my_app',
);

public $stage = array(
    'environment' => array('test.domain.com'),
    'path' => array('/some/stage/path/to/app/'),
    'datasource' => 'Database/Mysql',
    'host' => 'localhost',
    'login' => 'root',
    'password' => '123',
    'database' => 'my_app_stage',
);

public $live = array(
    'environment' => array('www.domain.com', 'domain.com'),
    'path' => array('/some/live/path/to/app/'),
    'datasource' => 'Database/Mysql',
    'host' => 'localhost',
    'login' => 'root',
    'password' => '456',
    'database' => 'my_app_live',
);

Note: In all cases the test config will adjust itself to the current environment as we didn’t specify anything for it.

Final notes – some pitfalls and tips

Make sure you put the exact paths to your application in path – including the trailing slash!
If you want to confirm that everything works in CLI, as well, use my CurrentConfig shell to output the current configuration for the console:

..\lib\Cake\Console\cake Setup.CurrentConfig

It should then display the default and test DB config as well as the current Cache config.

Other solutions

There are some newer similar solutions in form of plugins available now. Check out for cakephp-environments instance.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.