I'm developing a system in CakePHP, using Git as the version control system. I have a working copy in my testing server and another in my production server, both with different databases. Everytime I make changes, I have to change the database configuration so I can test the system. Is there another way to keep two files, with different contents, one in the test and another in the production server? Branches are a good way to go?
You wouldn't want to do that with branches. I can't speak to PHP specifically, but rather than keep the two files (test config & production config) in separate branches, you'd keep them together, but just let an environment variable determine which config is the correct one to use at runtime.
(This is how it's done in Rails and it works well.)
If the database is dependent on the environment, you can do something like this in the database.php
file:
class DATABASE_CONFIG {
var $default = NULL;
var $prod = array(
'driver' => 'mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'username',
'password' => 'password',
'database' => 'productionDatabaseName',
'prefix' => '',
);
var $staging = array(
'driver' => 'mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'username',
'password' => 'password',
'database' => 'stagingDatabaseName',
'prefix' => '',
);
//var $dev = ...
// Chooses production or staging depending on URL
function __construct ()
{
if(isset($_SERVER['SERVER_NAME']))
{
switch($_SERVER['SERVER_NAME'])
{
case 'myhostname.com':
case 'www.myhostname.com':
$this->default = $this->prod;
break;
case 'staging.myhostname.com':
$this->default = $this->staging;
break;
default:
$this->default = $this->dev;
}
}
else // Use local for any other purpose
{
$this->default = $this->dev;
}
}
}
I've gone for a rather crude but effective technique: In my development environment I have an empty file called 'environment_development'. In my production environment I have one called 'environment_PRODUCTION' (different case for added visual emphasis). My gitignore file is set to ignore both of these.
The front controller of my application (I use the Kohana framework, but I'm presuming CakePHP has something similar) checks for the presence of these files and sets an IN_PRODUCTION constant appropriately. The rest of the code (database configuration, error handling etc.) can check the value of this constant and alter behaviour as required.
I used to use the $_SERVER['SERVER_NAME'] check, but this method has the following advantages:
- It works even if there are parts of your app you want to run from the command line, e.g., as cronjobs, when $_SERVER is not set.
- It works even if your app runs on multiple domains.
- It is entirely explicit: if someone checks out another working copy of the app, nothing will function until they create an environment file, so there's no (or very little) chance of someone running development code against the production db or vice versa.