Quick and dirty 'Down for Maintenance' page with CakePHP

Websites need maintenance, and sometimes that maintenance requires the site to go down for a little bit as you tweak the database, add additional capacity or make large changes to the application code. In these circumstances you cannot afford to have users mucking about on your application. However, you might need access to ensure all your amazing upgrades go smoothly or perhaps do the upgrading inside the application itself. I’ve come up with a quick and dirty solution that has served me well in the past. It requires one additional config setting and a little bit more logic in your AppController.

Light switch

I like to keep my off switch as a Configure var. This makes it easy to use and congruent with other settings in core. I usually add the following to my app/config/bootstrap.php.

Show Plain Text
  1. Configure::write('App.maintenance', false);
  2.  

Now I have an easy way to switch off the application, just change false to true and transfer the file to the server.

Lights out

In my applications I like my ‘root’ account to continue having access to the application as I make changes. As a rule my ‘root’ account is always id 1 in the users table. This has other benefits as well. I can easily check and override any permission settings by comparing the user.id in the session to 1. To accomplish a shutdown I simply raises a cakeError when the Configure setting is true and the logged in user is not id 1, effectively locking every page for every user unless they are the ‘root’ user.

In AppController::beforeFilter() I add the following.

Show Plain Text
  1. if (Configure::read('App.maintenance')) {
  2.     if ($this->Auth->user('id') !== 1) {
  3.         $message = __('We are currently working on the application, please check back later.', true);
  4.         $this->cakeError('error', array(
  5.                         array( 'code' => '403',
  6.                                'name' => __('Application down for maintenance', true),
  7.                                'message' => $message,
  8.                                'title' => __('Maintenance', true),
  9.                                'base' => $this->base,
  10.                                'url' => $this->here)
  11.                         ));
  12.         exit();
  13.     }
  14. }

I find this to be a quick and easy way that doesn’t require a lot of work, but is effective in shutting down an application for a short period of time. When active, every url draws the same page, and prevents any other logic from executing.

Does anyone else have an even easier, and or better way to do this?

Comments

I really don’t know but maybe something like a 503 would be better suited?!? $this->header(‘HTTP/1.1 503 Service Temporarily Unavailable’); $this->header(‘Status: 503 Service Temporarily Unavailable’); $this->header(‘Retry-After: 7200’); // 2 hours

On the other hand you’re a right when you send a Forbidden because it’s (temporarly) forbidden to access that page…

By the way do you know how I can control which status header cake sends when you call $this->cakeError?
As far as I can see the ‘code’ parameter does not set the status header.

anonymous user on 27/7/08

Hi Mark,

Just thought I’d mention I’ve been having some trouble with your RSS feed in that it keeps downloading articles I already have…

anonymous user on 30/7/08

Hello, please check this (slightly outdated) post:

http://blog.devayd.com/2008/05/maintenance-module/

we have done something similar, but adding controller/view for a better apperance and password/cookies check so this can be used for testing while the site is not available to regular users.

you can grab the latest code from here: http://anon:anon@websvn.devayd.com/wsvn/public/modules/maintenance/#_modules_maintenance_

regards
daniel

anonymous user on 14/9/08

Thank you! How would you do this in CakePHP 2.1.0?

Nick on 9/3/12

That’s not quick and dirty enough. How about something like this at the top of your public index.php. Works with all versions of cake.

@ define(‘MAINTENANCE’, 0); if(MAINTENANCE > 0 && $_SERVER[‘REMOTE_ADDR’] != ’188.YOUR.IP.HERE’){ require(‘maintenance.php’); die(); }

@

This allows you to view the site your home/office and keep if down to the world. You will still need to make a separate maintenance page.

Joel on 12/3/12

Have your say:

*
* You can use Textile markup, but be reasonable