Simple Site Maintenance Mode with CakePHP 1.2

The ability to put a website into offline or ‘maintenance’ mode seems like a pretty common request these days - it certainly was one of the more important things in the list for me when I was beginning my CMS. Thanks to the beforeFilter() method in CakePHP’s AppController, we can add the ability to turn a website off and on to visitors easily; here’s how I did it.

Adding a ‘maintenance mode’ (or “Site Online/Offline” feature as I call it in my CMS) is actually pretty simple, and just involves a few steps. I have the offline/online toggle as a switch in the admin area of my CMS, but for the sake of simplicity I’ll just make it a hard-coded variable here (putting the option in your CMS should be pretty simple). Here’s what we’ll do:

  • Add the Necessary Variables to the Core
  • Check the Status in AppController

I told you it was easy! So…

Add the Necessary Variables to the Core

As I mentioned, I set the status of my sites in the admin area of my CMS. The status belongs to the settings table, which, as the name might suggest, stores a bunch of different site settings. But for the sake of simplicity we’ll just set what we need in /app/config/core.php.

We need two variables, ’site_status’ and ’site_offline_url’. So, in /app/config/core.php, add this:

Configure::write('SiteSettings.site_status', 'Offline');
Configure::write('SiteSettings.site_offline_url', '/coming-soon');

They’re both pretty straightforward: set ’site_status’ to either ‘Offline’ or ‘Online’ as you see fit, and set ’site_offline_url’ to the URL to which you want to redirect visitors.

Check the Status in AppController

Now that we’ve got our variables, we just need to add a simple bit of code in AppController::beforeFilter() which will check the status of the site and redirect if necessary. I’ll do two versions: one dead simple, and one a little more complex that includes logic to allow for a login system.

The simple version:

function beforeFilter() {
    ...
    if (Configure::read('SiteSettings.site_status') == 'Offline'
        && $this->here != Configure::read('SiteSettings.site_offline_url')) {
        $this->redirect(Configure::read('SiteSettings.site_offline_url'));
    }
}

The slightly-more-complex-but-still-pretty-simple version:

function beforeFilter() {
    ...
    if (Configure::read('SiteSettings.site_status') == 'Offline'
        && $this->here != Configure::read('SiteSettings.site_offline_url')) {
        if ($this->action != 'login' && $this->action != 'logout'
        && !in_array('*', (array)$this->Session->read('Permissions'))) {
            $this->redirect(Configure::read('SiteSettings.site_offline_url'));
        }
    }
}

Of course you may have to change the code a bit depending on how you deal with Permissions. In this example, I’m using a permission system inspired by studiocanaria.com’s  non-ACL Auth component implementation, but adding ACL support (which I found to be just a little too heavyweight for my needs) should be a straightforward task. Basically, if the user isn’t trying to login and isn’t an admin, they get redirected to the site offline page.

And that’s it. Your visitors will now be redirected to a predefined URL if your site is in offline ‘maintenance’ mode. Lots of room for extension with this simple code. Some ideas off the cuff:

  • Add the variables to your admin area
  • Use a different layout for the site offline URL
  • Put a contact form on the page
  • etc.

A more robust implementation would probably be best as a component, rather than just a couple of lines of code in AppController::beforeFilter(). But I would suggest that most small-to-medium sites can probably get by just fine with this. A component would most certainly be “cakier”, and I may rewrite this as a component eventually. But for now, here you go. ;)