If you want to deploy your cakephp app you usually have to change a few lines of code. But we want to minimize that.
My example setup: - development: Windows (>= Vista) - productive: Linux (Debian)
Database Setup
Create a library file and extend this from your DATABASE_CONFIG. This way you can let your app automatically select the correct database var at runtime.
class BASE_CONFIG { var $environments = array('default', 'sandbox', 'online'); var $default = array(); /** * switch between local and live site(s) automatically by domain * or manually by Configure::write('Environment.name') * 2009-05-29 ms */ function __construct() { $environment = $this->getEnvironmentName(); if ($environment && isset($this->{$environment})) { $this->default = array_merge($this->default, $this->{$environment}); } $this->test = $this->default; $this->test['prefix'] = 'zzz_'; } function getEnvironmentName() { $environment = (String)Configure::read('Environment.name'); if (empty($environment) && !empty($_SERVER['HTTP_HOST'])) { $server = (String)$_SERVER['HTTP_HOST']; if (!empty($server)) { foreach ($this->environments as $e) { if (isset($this->{$e}) && isset($this->{$e}['environment']) && $this->{$e}['environment'] == $server) { $environment = $e; break; } } } } return $environment; } }
Example for your database.php:
App::import('Lib', 'BaseConfig'); class DATABASE_CONFIG extends BASE_CONFIG { var $default = array( // localhost 'name' => 'default', 'environment' => 'localhost', 'driver' => 'mysqli', 'persistent' => false, 'host' => 'localhost', 'login' => 'root', 'password' => '', 'database' => 'cake_app', 'prefix' => 'xyz_', 'encoding' => 'utf8' ); var $sandbox = array( // online test 'name' => 'test', 'environment' => 'test.domain.com', 'login' => 'root', 'password' => '', 'database' => 'cake_app_test', ); var $online = array( // online productive 'name' => 'online', 'environment' => 'www.domain.com', 'login' => 'root', 'password' => '', 'database' => 'cake_app', ); }The same config file on all 3 locations will now select the one corresponding to the environment url. You could override this, though, by using Configure::write(‘Environment.name’) – but this is not necessary if the domain doesnt change too often.
Debug Mode
Put this in your core.php (it should ALWAYS be 0 by default!):
Configure::write('debug', 0); # Enhancement if (!empty($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST'] == 'localhost') { Configure::write('debug', 2); }Debug mode is 0 for all online sites and 2 for your local development site.
Custom “Overrides”
There are many variables you need to switch from local to live apps (google.maps key, other api keys, email server credentials, …) The quick-and-dirty solution would be something like this:
if ($_SERVER['HTTP_HOST'] == 'localhost') { $config['Foo'] = array(1,2,3); } elseif ($_SERVER['HTTP_HOST'] == 'www.domain.com')) { $config['Foo'] = array(1,2,4); } else { $config['Foo'] = array(1,5,6); }Very fast very ugly.
A little bit cleaner is using two config files: “configs.php” and “configs_private.php”. The second one is not synched (or in SVN) – it contains passwords and environment specific content. Include it in your bootstrap AFTER you included the default configs.
As i just mentioned, it has another upside: Beeing a environment based tmp-file it does not store any sensitive information in the SVN (or whatever other backup tool you use). This way you can easily set up configuration “stubs” in your configs.php and insert the passwords in your private config file.
Folder Setup and .htaccess
You can use the same folder setup: - cake - app - vendors With …/app/webroot/ as “visible folder” and …/app/webroot/index.php as dispatching script.
In my htaccess file i use “!^localhost” to avoid redirects locally:
RewriteCond %{HTTP_HOST} !^www\. [NC] RewriteCond %{HTTP_HOST} !^localhost [NC] RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]This way the same file can be used for both environments.
Linux/Windows differences
Use the constant DS (= Directory Separator) anywhere you can. If you hardcode it with / (Linux) oder \ (Windows) it might break some code. Usually it doesn’t, but it is cleaner to use DS anyway.
Example:
file_put_contents(TMP.'xyz'.DS.'file.txt', 'some text')
Set up a WINDOWS constant in your bootstrap.php – this way you can dynamically decide what function to use or to not use specific lines of code (like console “exec” commands).
if (substr(PHP_OS, 0, 3) == 'WIN') { define('WINDOWS', true); } else { define('WINDOWS', false); }
Example:
if (WINDOWS) { //whatever } else { exec($something); }
Uploading your changes
I use a shell tool i wrote – which uses “rsynch” and only uploads the delta (changes made so far). Make sure you DON’T upload any tmp stuff or even worse, override environment based files like uploads, cached files etc. Using batch scripts you can usually exclude some directories.
Final Tips
Remember that linux needs explicit folder permissions. So you need to manually (or per batch script) set /tmp to 777 recursivly as well as any other folder which you want to write into from your scripts.
Also clear the cache after updating! Otherwise your model relations as well as some constants will be outdated and cause errors or complete failure.
