ExpressionEngine on Multiple Machines
Doug Avery, Former Senior Developer
Article Category:
Posted on
For way too long, we managed our ExpressionEngine installs the terrifying way — one server, one install, one DNS update on launch. While this might sound fine to some of you (and it did to me at one point), it’s a really bad idea in practice. Once a site would reach a certain complexity, the management process started to break down. Having a single install, a single LIVE install, makes every task twice as complex and risky. Regular backups help at first, but pretty soon you have a big ball of awfulness that no one understands and no one wants to deal with. Upgrading addons and testing new features might seem simple when your site is in its infancy, but these tasks become seriously painful on a large live site.
I held the assumption that this wasn't a process problem but an EE one — there just wasn’t a good way to have multiple copies of the same EE site running in harmony and easily syncing with eachother. It turns out I was wrong, there's actually plenty you can do to have multiple team members working with their own copies of an install and pushing to a live site. Here are a few ideas that have helped me with the process.
Git - Put your install in git, and dump the database into something like /data/db_dump.sql. Version control is a MUST here, even though it doesn't solve one of EE’s biggest issues, that the DB holds 99% of the work you do an a site. Which brings us to...
Saving templates as files - A must for group work, for two reasons. One, templates are *much* easier to edit as files, so much so that I almost wish I could disable the template manager altogether. The second reason is that moving this data to files makes it easier to track, merge, and roll back changes in version control.
Config.php and database.php - The key is to move as many settings out of the DB and into config.php as you can. For example, here's my default config at the moment:
// Site basics $config['app_version'] = "213"; $config['install_lock'] = ""; $config['license_number'] = "XXXX-XXXX-XXXX-XXXX"; $config['debug'] = '1'; $config['site_label'] = 'EEbase'; $config['is_system_on'] = 'y'; // Paths $config['site_url'] = "http://{$_SERVER['HTTP_HOST']}/"; $config['base_path'] = $_SERVER['DOCUMENT_ROOT']; $config['cp_url'] = $config['site_url'] . 'ee-system/index.php'; $config['theme_folder_url'] = $config['site_url'] . 'themes/'; $config['theme_folder_path'] = $config['base_path'] . 'themes/'; // Templates $config['save_tmpl_files'] = 'y'; $config['tmpl_file_basepath'] = $config['base_path'] . 'ee-system/expressionengine/templates/'; // Custom additions (modify if you want to use tasks/minify scripts) $config['main_theme'] = 'site_name'; $config['js_files'] = array( 'jquery', 'jquery.animate_rotate_scale', 'jquery.carousel', 'lettering', 'application' ); $config['css_files'] = array( 'screen' ); ... (the rest of the default config continues from)
Notice how it re-uses variables as much as possible and depends one $_SERVER vars for paths (thanks to a great tip from Brian Warren), so getting a site running shouldn’t require any big changes. I recently added some custom settings pertaining to the theme I use (more on that later) and the order of files I want to minify. The config might not be the best place for this, but I like having all these modification options together in as few files as possible. Once you have your ideal setting in place, make copies of database.php and config.php and name them config.php.sample and database.php.sample, so future devs can use your template for their own versions.
.gitignore - After you commit these files, you'll need to make a .gitignore file that ensures you don't accidentally overwrite someone else's config later on in the project. Put it in the root dir of the project:
system/expressionengine/config/database.php system/expressionengine/config/config.php .DS_Store current_version */expressionengine/cache/*
(For more on using .gitignore with EE, check out Github’s suggested template.)
CSS, JS, images - I prefer to move these out of templates entirely and keep them in /themes/my_site_name/, but to each his/her own. The advantages of keeping them in themes:
- You can store them there with the original markup, so while one team member works on the EE side of things, another can do buildout, and the two processes will flow together nicely. If a new page needs to be built in the future, the "handoff" is a lot simpler, since the full site and the flat markup are using all of the same files.
- Fewer DB hits for EE to worry about.
- Less duplication of code
- You're keeping related images, CSS, and JS together in a place where they can be easily separated, renamed, or replaced
The biggest downside to moving CSS out of the templates is that you miss out on EE's automatic cachebusting - but EE doesn't do this for JS anyway, so you'll need to find an alternative method no matter what. I like Adam Spooner's idea of just using a template variable.
Managing the Database - The most painful part of all this is probably the DB, which needs to be exported and imported before pushes and after pulls. I handle it with a little folder full of PHP scripts which, when run from the project root, do all the dirty work for me. You can download them here, and run them like so from the command line: "php tasks/import_db.php"
- import_db.php - Import for the first time, or after pulling from repo
- export_db.php - Export before pushing
- minify_css.php - Minify CSS files (specified in config.php) to 'all.min.css' in your theme folder
- minify_js.php - Minify JS to 'all.min.js'
To run these the way I set them up, you’ll need to add an extra line to your database.php file that points the scripts to the correct mysql:
$db['expressionengine']['path_to_mysql_command'] = "/Applications/MAMP/Library/bin/";
Minification - EE doesn't offer much in the way of automatic minification at the moment, but I include a copy of YUI compressor in the tasks folder, along with scripts to minify the JS and CSS in a theme. It’s not too sophisticated, but it's usually enough for an EE build. The two minification extensions I’ve seen (NSM Minify and Minimee) don’t quite offer the level of control I’m looking for, and honestly, running a little script is easier for me than using an extension. As I noted earlier, I’m playing with the idea of keeping the array of file to minify in the config.php itself.
Deployment - Up until now, the final deployment process has been to log into the server and run git pull and them import_db, but we’re looking into more elegant options like Dan Benjamin's Capistrano setup.
How are you deploying EE? How are you sharing and developing projects locally? Let me know in the comments.