Simple application maintenance mode
If you need a simple application maintenance mode, fear not! CakePHP has you covered!
We’ll need to create a custom Dispatch Filter:
<?php
// In Lib/Routing/Filter/MaintenanceMode.php
App::uses('DispatcherFilter', 'Routing');
class MaintenanceMode extends DispatcherFilter {
public function beforeDispatch(CakeEvent $event) {
if (!Configure::read('MaintenanceMode.enabled')) {
return;
}
$event->data['response']->statusCode(503);
$event->data['response']->body('503 Service Unavailable');
$event->stopPropagation();
return $event->data['response'];
}
}
?>
Now we can attach it to our existing dispatch filters:
<?php
// in our bootstrap.php
App::uses('MaintenanceMode', 'Lib/Routing/Filter');
Configure::write('Dispatcher.filters', array(
'AssetDispatcher',
'CacheDispatcher',
'MaintenanceMode', // our new filter here!
));
?>
Tada! Now turning on maintenance mode is as simple as Configure::write('MaintenanceMode.enabled', 1)
!
Using custom views
The above is lame in that it only works for a simple 503 error page. What if you want to use a custom status code, or maybe a custom view file?
To do this, lets change our filter a bit:
<?php
// In Lib/Routing/Filters/MaintenanceMode.php
App::uses('DispatcherFilter', 'Routing');
class MaintenanceMode extends DispatcherFilter {
public function beforeDispatch(CakeEvent $event) {
if (!Configure::read('MaintenanceMode.enabled')) {
return;
}
$statusCode = Configure::read('MaintenanceMode.code');
$statusMessage = Configure::read('MaintenanceMode.message');
if (!$statusCode) {
$statusCode = 503;
$statusMessage = '503 Service Unavailable';
}
if (!$statusMessage) {
$statusMessage = $statusCode . ' Currently undergoing maintenance';
}
$event->data['response']->statusCode($statusCode);
$event->data['response']->body($statusMessage);
$event->stopPropagation();
return $event->data['response'];
}
}
?>
At this point, we can configure a custom status code and a custom message. Lets add the ability to use a custom view:
<?php
protected function _getView() {
$helpers = Configure::read('MaintenanceMode.helpers');
if (empty($helpers) || !is_array($helpers)) {
$helpers = array('Html');
}
$View = new View(null);
$View->viewVars = Configure::read('MaintenanceMode');
$View->helpers = $helpers;
$View->loadHelpers();
$View->hasRendered = false;
$View->viewPath = 'MaintenanceMode';
return $View;
}
?>
We’ll need to modify our beforeDispatch
, where we set the response body:
<?php
$template = Configure::read('MaintenanceMode.template');
if ($template) {
$View = $this->_getView();
$body = $View->render($template, Configure::read('MaintenanceMode.layout'));
$event->data['response']->body($body);
} else {
$event->data['response']->body($statusMessage);
}
?>
And add the App::uses('View', 'View');
call to the top of your MaintenanceMode
class. Now to use a custom view, we’d create a file in app/View/MaintenanceMode/index.ctp
with our content, a app/View/MaintenanceMode/maintenance.ctp
layout, and then configure our filter as follows:
<?php
Configure::write('MaintenanceMode', array(
'enabled' => true,
'helpers' => 'Html',
'layout' => 'maintenance',
'template' => 'index'
));
?>
You can extend this as far as you need, and here are a couple of ideas:
- Add ajax request support
- Enable custom view classes
- Allow maintenance mode to be enabled via the existence of a file, or an environment variable
- Have this affect background processes
- Add unit tests!
If you need some downtime this Christmas, CakePHP has your back!