Configuring CakePHP for easy deployment
Whenever you are developing an application, you are normally using at least 2 environments: development and production. Depending on how big your app and database are, deployment may become a long list of to-dos in order to have everything setup correctly (database changes, code merges, apache configuration, etc.). When you want to do things the right way, you usually have a 3rd environment, staging. Yes, another almost identical to-do list.
Now imagine you are developing in a team with each member working on a different part of the application in individual branches on the repository. New features are only merged with the team’s branch (development) after they are tested individually. So now, you have to deploy from individual to development, then to staging before finally pushing updates to production.
This time-consuming process is definitely not the best solution, put aside the fact that it is bound to break with any mistake while reconfiguring everything. Today, we will automate CakePHP’s configuration for easy deployment.
Our needs
- Smoothly switch over 6 different databases (3+ personaldbs, developmentdb, stagingdb and productiondb), over 6 different application directories and as many CakePHP core releases.
- Have different debug, caching, session, etc. core defines for each mode.
Solution
I had to edit the usual 3 configuration files:- /app/config/core.php: For all the defines
- /app/config/database.php: For the different databases
- /app/webroot/index.php: For the paths and to call a custom configuration file. I had to call it from index.php instead of bootstrap.php because it includes the required defines for Cake’s bootstrapping which comes before the custom bootstrap.
<?php
define('DEBUG', DEBUG);
define(’CACHECHECK’, __CACHECHECK);
define(’LOGERROR’, __LOGERROR);
define(’CAKESESSIONSAVE’, __CAKESESSIONSAVE);
define(’CAKESESSIONTABLE’, __CAKESESSIONTABLE);
define(’CAKESESSIONSTRING’, __CAKESESSIONSTRING);
define(’CAKESESSIONCOOKIE’, __CAKESESSIONCOOKIE);
define(’CAKESECURITY’, __CAKESECURITY);
define(’CAKESESSIONTIMEOUT’, __CAKESESSIONTIMEOUT);
define(’CAKEADMIN’, __CAKEADMIN);
define(’WEBSERVICES’, __WEBSERVICES);
define(’COMPRESSCSS’, __COMPRESSCSS);
define(’AUTOSESSION’, __AUTOSESSION);
define(’MAXMD5SIZE’, __MAXMD5SIZE);
define(’ACLCLASSNAME’, __ACLCLASSNAME);
define(’ACLFILENAME’, __ACLFILENAME);
define(’ACLDATABASE’, __ACLDATABASE);
define(’CACHEDEFAULTDURATION’, __CACHEDEFAULTDURATION);
define(’CACHEGCPROBABILITY’, __CACHEGCPROBABILITY);
$cakeCache = $cakeCache;
?>
/app/config/database.php after the changes:
<?php
class DATABASE_CONFIG {
var $default = null;
var $production = array(
‘driver’ => ‘mysql’,
‘persistent’ => false,
‘host’ => ‘123.123.123.123′,
‘login’ => ‘user’,
‘password’ => ‘pass’,
‘database’ => ‘prod_db’,
‘prefix’ => ”
);
var $staging = array(
‘driver’ => ‘mysql’,
‘persistent’ => false,
‘host’ => ‘123.123.123.123′,
‘login’ => ‘user’,
‘password’ => ‘pass’,
‘database’ => ’stag_db’,
‘prefix’ => ”
);
var $development = array(
‘driver’ => ‘mysql’,
‘persistent’ => false,
‘host’ => ‘123.123.123.123′,
‘login’ => ‘user’,
‘password’ => ‘pass’,
‘database’ => ‘dev_db’,
‘prefix’ => ”
);
var $individual = array(
‘driver’ => ‘mysql’,
‘persistent’ => false,
‘host’ => ‘123.123.123.123′,
‘login’ => ‘user’,
‘password’ => ‘pass’,
‘database’ => ‘indv_db’,
‘prefix’ => ”
);
function DATABASE_CONFIG(){
$this->default = $this->{ENVIRONMENT};
}
}
?>
/app/webroot/index.php after the changes: (showing only the part that comes before the ‘DO NOT EDIT BELOW THIS LINE’ notice)
/**
* Do not change
*/
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
/**
* Call for custom configuration file.
*/
include_once('..' . DS . 'config' . DS . 'config.php’);
/**
* These defines should only be edited if you have cake installed in
* a directory layout other than the way it is distributed.
* Each define has a commented line of code that explains what you would change.
*/
if (!defined(’ROOT’)) {
//define(’ROOT’, ‘FULL PATH TO DIRECTORY WHERE APP DIRECTORY IS LOCATED. DO NOT ADD A TRAILING DIRECTORY SEPARATOR’);
//You should also use the DS define to separate your directories
define(’ROOT’, ROOT);
}
if (!defined(’APPDIR’)) {
//define(’APPDIR’, ‘DIRECTORY NAME OF APPLICATION’);
define(’APP_DIR’, __APP_DIR);
}
/**
* This only needs to be changed if the cake installed libs are located
* outside of the distributed directory structure.
*/
if (!defined(’CAKE_CORE_INCLUDE_PATH’)) {
//define (’CAKE_CORE_INCLUDE_PATH’, ‘FULL PATH TO DIRECTORY WHERE CAKE CORE IS INSTALLED. DO NOT ADD A TRAILING DIRECTORY SEPARATOR’);
//You should also use the DS define to separate your directories
define(’CAKE_CORE_INCLUDE_PATH’, __CAKE_CORE_INCLUDE_PATH);
}
The custom configuration file I created ‘config.php’ was placed in /app/config/ and contained something like this:
<?php
/**
* Defines the environement
*/
switch($_SERVER['HTTP_HOST']){
case ’staging.example.com’:
define(’__ENVIRONMENT’, ’staging’);
break;
case ‘development.example.com’:
define(’__ENVIRONMENT’, ‘development’);
break;
case ‘name.example.com’:
define(’__ENVIRONMENT’, ‘individual’);
break;
default:
define(’__ENVIRONMENT’, ‘production’);
}
switch(__ENVIRONMENT){
case ’staging’:
/**
* Core Defines
*/
define(’DEBUG’, 2);
define(’CACHE_CHECK’, false);
define(’LOG_ERROR’, 2);
define(’CAKE_SESSION_SAVE’, ‘php’);
define(’CAKESESSIONTABLE’, ‘cake_sessions’);
define(’CAKE_SESSION_STRING’, ‘ANYSESSIONKEYHERE’);
define(’CAKESESSIONCOOKIE’, ‘CAKEPHP’);
define(’CAKE_SECURITY’, ‘high’);
define(’CAKESESSIONTIMEOUT’, ‘120′);
define(’CAKE_ADMIN’, ‘admin’);
define(’WEBSERVICES’, ‘off’);
define(’COMPRESS_CSS’, false);
define(’AUTO_SESSION’, true);
define(’MAX_MD5SIZE’, (5 * 1024) * 1024);
define(’ACLCLASSNAME’, ‘DBACL’);
define(’ACL_FILENAME’, ‘db_acl’);
define(’ACL_DATABASE’, ‘default’);
define(’CACHE_DEFAULT_DURATION’, 0);
define(’CACHEGCPROBABILITY’, 3);
$cakeCache = array(’File’);
/**
* Paths
*/
define('__ROOT', '/path/to/app');
define('__APP_DIR', 'appfolder');
define('__CAKE_CORE_INCLUDE_PATH', '/path/to/cake/core');
break;
case ‘development’:
/**
* Core Defines
*/
define(’DEBUG’, 3);
define(’CACHE_CHECK’, false);
define(’LOG_ERROR’, 2);
define(’CAKE_SESSION_SAVE’, ‘php’);
define(’CAKESESSIONTABLE’, ‘cake_sessions’);
define(’CAKE_SESSION_STRING’, ‘ANYSESSIONKEYHERE’);
define(’CAKESESSIONCOOKIE’, ‘CAKEPHP’);
define(’CAKE_SECURITY’, ‘high’);
define(’CAKESESSIONTIMEOUT’, ‘120′);
define(’CAKE_ADMIN’, ‘admin’);
define(’WEBSERVICES’, ‘off’);
define(’COMPRESS_CSS’, false);
define(’AUTO_SESSION’, true);
define(’MAX_MD5SIZE’, (5 * 1024) * 1024);
define(’ACLCLASSNAME’, ‘DBACL’);
define(’ACL_FILENAME’, ‘db_acl’);
define(’ACL_DATABASE’, ‘default’);
define(’CACHE_DEFAULT_DURATION’, 0);
define(’CACHEGCPROBABILITY’, 3);
$cakeCache = array(’File’);
/**
* Paths
*/
define('__ROOT', '/another/path/to/app');
define('__APP_DIR', 'appfolder');
define('__CAKE_CORE_INCLUDE_PATH', '/path/to/cake/release1');
break;
case ‘individual’:
/**
* Core Defines
*/
define(’DEBUG’, 3);
define(’CACHE_CHECK’, false);
define(’LOG_ERROR’, 2);
define(’CAKE_SESSION_SAVE’, ‘php’);
define(’CAKESESSIONTABLE’, ‘cake_sessions’);
define(’CAKE_SESSION_STRING’, ‘ANYSESSIONKEYHERE’);
define(’CAKESESSIONCOOKIE’, ‘CAKEPHP’);
define(’CAKE_SECURITY’, ‘high’);
define(’CAKESESSIONTIMEOUT’, ‘120′);
define(’CAKE_ADMIN’, ‘admin’);
define(’WEBSERVICES’, ‘off’);
define(’COMPRESS_CSS’, false);
define(’AUTO_SESSION’, true);
define(’MAX_MD5SIZE’, (5 * 1024) * 1024);
define(’ACLCLASSNAME’, ‘DBACL’);
define(’ACL_FILENAME’, ‘db_acl’);
define(’ACL_DATABASE’, ‘default’);
define(’CACHE_DEFAULT_DURATION’, 0);
define(’CACHEGCPROBABILITY’, 3);
$cakeCache = array(’File’);
/**
* Paths
*/
define('__ROOT', '/and/another/path/to/app');
define('__APP_DIR', 'appfolder');
define('__CAKE_CORE_INCLUDE_PATH', '/path/to/cake/release2');
break;
default:
/**
* Core Defines
*/
define(’DEBUG’, 0);
define(’CACHE_CHECK’, true);
define(’LOG_ERROR’, 2);
define(’CAKE_SESSION_SAVE’, ‘php’);
define(’CAKESESSIONTABLE’, ‘cake_sessions’);
define(’CAKE_SESSION_STRING’, ‘OFFICIALSESSIONKEY’);
define(’CAKESESSIONCOOKIE’, ‘WEBAPPNAME’);
define(’CAKE_SECURITY’, ‘high’);
define(’CAKESESSIONTIMEOUT’, ‘120′);
define(’CAKE_ADMIN’, ‘admin’);
define(’WEBSERVICES’, ‘off’);
define(’COMPRESS_CSS’, false);
define(’AUTO_SESSION’, true);
define(’MAX_MD5SIZE’, (5 * 1024) * 1024);
define(’ACLCLASSNAME’, ‘DBACL’);
define(’ACL_FILENAME’, ‘db_acl’);
define(’ACL_DATABASE’, ‘default’);
define(’CACHE_DEFAULT_DURATION’, 0);
define(’CACHEGCPROBABILITY’, 3);
$cakeCache = array(’File’);
/**
* Paths
*/
define('__ROOT', '/yet/another/path/to/app');
define('__APP_DIR', 'appfolder');
define('__CAKE_CORE_INCLUDE_PATH', '/path/to/cake/release2');
}
?>
Now you can move your app directory around without worrying about CakePHP’s configuration.
Here are links I think you will find easier to implement when you are using a basic development/production and don’t have to toggle among all these different configurations:
Trackbacks
Use this link to trackback from your own site.

