Automatically choose database connections in CakePHP

2008 July 5
by Eddie

When developing applications it is wise to isolate development environments from live production environments. This is true of your code and your database structures

For me this means my local SuSE server runs any developmental code before I push it off to a shared hosting account out on the real live web.

The frustrating part for me was changing between two distinct database connections. Every time I uploaded the complete application I would need to manually change connection strings.

Well no more! A simple logic switch can do the work for me (and you), hooray!.

Old database.php

class DATABASE_CONFIG
{
	var $default = 
		array(
			'driver' => 'mysql',
			'connect' => 'mysql_connect',
			'host' => 'localhost',
			'login' => 'cakeuser',
			'password' => 'cake4ever',
			'database' => 'site_db',
			'prefix' => 'mydb_'
		);
}

Improved database.php

class DATABASE_CONFIG
{
	//initalize variable as null
	var $default=null;
 
	//set up connection details to use in Live production server
	var $prod = 
		array(
			'driver' => 'mysql',
			'connect' => 'mysql_connect',
			'host' => 'mysql123.example.com',
			'login' => 'username',
			'password' => 'pa55word',
			'database' => 'dbname',
			'prefix' => 'dbpre_'
		);
 
	// and details to use on your local machine for testing and development
	var $dev = 
		array(
			'driver' => 'mysql',
			'connect' => 'mysql_connect',
			'host' => 'localhost',
			'login' => 'username',
			'password' => 'password',
			'database' => 'baungenjar',
			'prefix' => 'dbpre_'
		);
 
 
	// the construct function is called automatically, and chooses prod or dev. UPdate! works for baking now
	function __construct ()
	{		
		//check to see if server name is set (thanks Frank)
		if(isset($_SERVER['SERVER_NAME'])){
			switch($_SERVER['SERVER_NAME']){
				case 'digbiz.localhost':
					$this->default = $this->dev;
					break;
				case 'digbiz.example.com':
					$this->default = $this->prod;
					break;
			}
		}
	    else // we are likely baking, use our local db
	    {
	        $this->default = $this->dev;
	    }
	}
}

What’s Happening

PHP provides a whole bunch of useful server variables, one of which is the name of the server hosting the scripts.

When the database class gets created, the construct function (if present) is called. This is true of any PHP class. We take advantage of this to check our server’s name before actually setting up the connections.

If we are not using the local server, then we set the default connection to use our production connection, otherwise we use our local connection.

NOTE: The order is important here, since CakePHP’s bake script will not have a server name, so we should always default to localhost, since thats where any backing would occur anyhow.

  • Share/Save/Bookmark
8 Responses leave one →
  1. 2008 July 11
    Nick permalink

    So sweet! I am having issues with baking though, any thoughts?

  2. 2008 July 22

    how about checking for db connection as well at this time and if db is down (ie site is down) redirecting to an error page?

  3. 2008 July 23
    admin permalink

    @Mandy
    I don’t that is something you would want to do in this class, since it comes before connections are made. But, cake has custom error pages based on missing tables.
    If you want something more advance you should visit Felix Geisendörfer’s article Handling database connection errors in CakePHP

  4. 2008 August 18

    @Nick I was also having trouble baking, check if $_SERVER isset to sort it out:

    if (isset($_SERVER['SERVER_NAME']) && !strstr($_SERVER['SERVER_NAME'], ‘localhost’)) { etc…

  5. 2008 August 23
    Eddie permalink

    @Frank

    Thanks Frank, that is a beautiful tip.

    @ Others..
    because baking is running as a script at the console, it does not have server values set. Thus you first check to see if they do not exist(meaning its a local bake), otherwise you may continue by checking names to distinguish development, performance and production servers.

  6. 2008 November 2

    Why not streamline all this if/else and just use the default: case

    //check to see if server name is set (thanks Frank)
    switch($_SERVER['SERVER_NAME']){
    case ‘digbiz.localhost’:
    $this->default = $this->dev;
    break;
    case ‘digbiz.example.com’:
    $this->default = $this->prod;
    break;
    default:
    // we are likely baking, use our local db
    $this->default = $this->dev;
    }

  7. 2009 February 3

    Small point, how about reducing it further?

    function __construct () {
    // Set default DB
    $this->default = $_SERVER['SERVER_NAME'] ==’digbiz.example.com’?$this->prod:$this->dev;
    }

  8. 2009 April 7

    This was very helpful, thanks! Solved a problem for me!

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS