lest I forget (Oli Studholme)

ExpressionEngine config.php setup for staging/production workflow

I want to develop and test on localhosting then use rsync to upload to production. Unfortunately ExpressionEngine has no idea about the whole localhosting/staging/production workflow thing. Luckily others solved this problem for me: (note: section = weblog = channel)

Initial setup

  • When making a template check the “save as file” option. Now you can create template group folders and template files locally to edit, use versioning, and upload the files to a staging server etc.
  • You might also want to use templates for content snippets (like section taglines) that would usually be Global Template Variables or articles in a snippets section, allowing these to also be versioned and shared between servers.
  • Make sure the system_folder variable is the same on all servers, ie if it’s in a subfolder on production, mimic this setup on localhost (it’s best to install on the server root though).
  • Remove the domain name from the image upload path, making it relative to the system folder: Admin → Section Admin → File Upload Preferences → ../images/uploads/
  • Remove the domain name from the paths in each section’s preferences when you make a new section: Admin → Section Admin → Section Management → Edit Section → Path Settings

Abstract system_folder and site_url variables

From Ken Wilson’s excellent article Configuring Expression Engine for multiple servers:

$site_url from Apache in path.php

Add this to path.php:

$site_url = "http://${_SERVER['HTTP_HOST']}/";

This gets the site URL from Apache, so we don’t need to directly configure it.

Add abstractions into config.php

The other thing we can set automatically is the folder path using ${_SERVER['DOCUMENT_ROOT']}, again via Ken Wilson:

// paths
$conf['system_folder'] = "cms"; // or whatever you use
$conf['site_url'] = "http://${_SERVER['HTTP_HOST']}/";
$conf['cp_url']   = "${conf['site_url']}${conf['system_folder']}/";
// templates
$conf['tmpl_file_basepath'] = "${_SERVER['DOCUMENT_ROOT']}/${conf['system_folder']}/templates";
// themes
$conf['theme_folder_path']  = "${_SERVER['DOCUMENT_ROOT']}/themes";
$conf['theme_folder_url']   = "${conf['site_url']}themes";
// captcha
$conf['captcha_path'] = "${_SERVER['DOCUMENT_ROOT']}/images/captchas";
$conf['captcha_url']  = "${conf['site_url']}images/captchas";
// member avatars
$conf['avatar_path']  = "${_SERVER['DOCUMENT_ROOT']}/images/members/avatars";
$conf['avatar_url']   = "${conf['site_url']}images/members/avatars";
// member photos
$conf['photo_path']   = "${_SERVER['DOCUMENT_ROOT']}/images/members/photos";
$conf['photo_url']    = "${conf['site_url']}images/members/photos";

I’ve replaced Ken’s http://${_SERVER['HTTP_HOST']} with ${conf['site_url']}.

Optionally move database settings into includes

If you don’t want to put database passwords for all servers into config.php, you can put them into includes (inspired by Jason Chrichton in an EE forum localhosting thread):

// include with relevant db etc settings
if($_SERVER['HTTP_HOST'] == 'www.production.com') {
include 'config-production.php';
} elseif($_SERVER['HTTP_HOST'] == 'www.staging.com') {
include 'config-staging.php';
} else {
include 'config-localhost.php';

Note: you’ll need to chmod 666 any config.php includes, and you can check HTTP_HOST via Admin → Utilities → PHP Info (toward the bottom)

Then you can add the database $conf values and anything else that differs between servers (like $conf['is_system_on'] or $conf['debug']) into the includes, then only upload the relevant include to each server. An example config-localhost.php file:

// Site.com; localhost config include
if ( ! defined('EXT')){
exit('Invalid file request');
$conf['db_hostname'] = "localhost";
$conf['db_username'] = "root";
$conf['db_password'] = "";
$conf['db_name'] = "site";

Extra config.php variables

Finally, here’s a list of extra config.php variables from the wiki for your copy & paste pleasure:

/* more variables via http://expressionengine.com/wiki/Hidden_Configuration_Variables/ */
// If set, when an {encode=""} tag is encountered, but emails are not to be encoded, this text will be displayed in place of the tag.
$conf['encode_removed_text'] = 'Encoded emails not allowed';

// If set, overrides the core Email class setting for crlf characters in quoted-printable encoded emails (Email class $crlf property).
$conf['email_crlf'] = "\r\n";

// If set, overrides the core Email class setting for newline characters (Email class $newline property).
$conf['email_newline'] = "\r\n";

// If a hidden template is encountered, the default behavior is to throw a 404.  With this set to ‘n’, the template group’s index page will be shown instead.
$conf['hidden_template_404'] = 'n';

// Set the character(s) to use at the beginning of a template name to consider it a “hidden” template. Default is a period ‘.’
$conf['hidden_template_indicator'] = '_';

//When set to “y” seconds are included on human-readable dates in the Control Panel forms.
$conf['include_seconds'] = 'y';

// Removes the textarea only restriction for custom fields in the moblog module.
$conf['moblog_allow_nontextareas'] = 'y';

// Determines whether or not links created by Typography class open in a new window.
$conf['popup_link'] = 'y';

// Prevents the advanced conditionals parser from processing anything in tags.
$conf['protect_javascript'] = 'y';

// How many seconds between PMs?
$conf['prv_msg_throttling_period'] = '60';

// How many hours after becoming a member until they can PM?
$conf['prv_msg_waiting_period'] = '48';

// Makes the title field gain focus when the page is loaded
$conf['publish_page_title_focus'] = 'n';

// Allows Entry View Tracking to work for ANY combination that results in only one entry being returned by the tag, including weblog query caching.
$conf['relaxed_track_views'] = 'y';

// Removes the Close All button from the Publish/Edit page and user side HTML formatting buttons.  Useful because most browsers no longer need it and Admins might want it gone
$conf['remove_close_all_button'] = 'y';

// When enabled, parsing of embedded templates that are not set to the template type “Static” will still be parsed as static if they can be (i.e. if they have no PHP or ExpressionEngine tags in them).  This setting is enabled by default.
$conf['smart_static_parsing'] = 'n';

// Allows you to specify the language used in the spellchecking functions.  Set the value to the two letter ISO 639 language code for the spellcheck (ex: en, es, de)
$conf['spellcheck_language_code'] = 'de';

// Determines whether the forums run at a different base URL than the main site.  Useful for running forums as a subdomain.
$conf['use_forum_url'] = 'y';

// Sets how many characters to display when viewing comments in the control panel.
$conf['view_comment_chars'] = '50';

// When set to ‘y’, creates <br >’s based on line breaks when viewing comments in the control panel.
$conf['view_comment_leave_breaks'] = 'y';

Nothing new, but hopefully this is of use to someone.

2009-11-30 Addenda: I received some feedback from @Choonkeat, who points out:

  • Updates will overwrite config.php—I haven’t been bothered by this because I’m versioning everything so I’ve just checked out the head config.php when necessary
  • Paths are saved into the database by 3rd party extensions etc—to address this Choonkeat has made a Ruby MySQL dump script to add the relevant info to the dump file. Bravo!

Again here’s hoping EE2.0 addresses this workflow problem.


  1. estantres reblogged this from boblet
  2. volker-rose reblogged this from boblet and added:
    Very useful information...multi-staging / deploying
  3. boblet posted this