Developing web applications you often need to have multiple configuration files for different development environments (DEV, QA, UAT, PROD etc). This can be solved by changing config file on the developers’ local machine, but this method has its drawbacks. For example, you should always ensure that while using VCS you will not accidentally commit your changes and which is not very comfortable from team development perspective.

We resolved this situation with the following decision:

Everything mentioned above was done for Yii Framework however it can be used in any other framework

To detect config file automatically we use Environment class. Thus, the first thing you should do is to copy file Environment.php into components folder of your project and link it in index.php.

require_once(dirname(__FILE__).'/protected/components/Environment.php');
$environment = new Environment(); //creating an object
$environment->setHost($_SERVER['HTTP_HOST']); // setting current host
$environment->setConfigDir(dirname(__FILE__).'/protected/config/'); //setting where to search config files
$config = $environment->getConfig(); // receiving appropriate file

the rest code can be left as is

require_once($yii); //linking Yii files
Yii::createWebApplication($config)->run(); //starting app with appropriate config

In the config folder (by default “/ protected / config /”), we create a file envs.php which defines config’s loading rules

return array(
       'coolproj.com' => 'prod',
       '*.coolproj.com' => 'subs',
       'qa.coolproj.com' => 'qa',
       'coolproj.local' => 'dev',
);

(all files should be located in folder specified in the setConfigDir() variable):

  • for the project located at qa.coolproj.com - file main.qa.php,
  • for coolproj.com – file main.prod.php
  • and for subdomains like sub1.coolproj.com – file main.subs.php

  • I should mention that original master file main.php will be loaded first, and files like main.qa.php, main.prod.php etc. will be loaded on top of it, overwriting only matching parameters. For example, file main.dev.php looks like this:

    return array(
           'components'=>array(
                   'db'=>array(
                           'connectionString' => 'mysql:host=localhost;dbname=coolproj_local',
                           'emulatePrepare' => true,
                           'username' => 'dev',
                           'password' => 'dev',
                           'charset' => 'utf8',
                   ),
           ),
    );

    then the only change in settings is database connection. All other settings will remain form file main.php

    Unfortunately, automatic detection does not work for console applications and tests, but environment can be set manually. To do this, change file yiic.php:

    $environment = new Environment();
    $environment->setEnv('prod'); // hardcode environment
    $environment->setIsWebApp(false); //setting application type
    $environment->setConfigDir(dirname(__FILE__).'/config/');

    In this case the logic remains the same as used in a web application. The only difference is that you should load files with “console” prefix, for example console.qa.php, console.prod.php etc.

    Through this approach, if a new developer comes to a project he needs to add only a separate rule for the URL to a local project and either create a configuration file or borrow it from the existing ones used by other developers.