I'm currently doing a custom ErrorHandler for an App in CakePHP. The reason? Well, bots are always trying to find stuff in your servers and sometimes they provoke exceptions and or errors.
The idea with this ErrorHandler is to filter requests and respond with the appropriate headers and prevent further request damage by handling this type of requests and make it transparent for the user client (because it might affect JavaScript for instance).
And what better way than to use the Framework's functionality, right?
The thing is that since this ErrorHandler is being used statically, well, there is no constructor so nothing inherits anything, it doesn't matter if you instantiate any other CakePHP Object.
What would be the appropriate way to use CakeResponse Object?
CakePHP's configuration:
app/Config/bootstrap.php:
App::uses('CustomErrorHandler', 'Lib');
app/Config/core.php:
// Error and exception handlers.
Configure::write('Error', array(
'handler' => 'CustomErrorHandler::handleError',
'level' => E_ALL & ~E_DEPRECATED,
'trace' => true
));
Configure::write('Exception', array(
'handler' => 'CustomErrorHandler::handleException',
'renderer' => 'ExceptionRenderer',
'log' => true
));
app/Lib/CustomErrorHandler.php:
... rest of class code ...
/**
* Named after convention: This method receives all CakePHP's
* errors and exceptions…
*
* @param array $e The exception object.
* @return mixed Returns the error handling or header redirection.
*/
public static function handleException($e)
{
$message = (string) $e->getMessage();
$code = (int) $e->getCode();
$file = (string) $e->getFile();
$line = (string) $e->getLine();
// If it's a Blacklist resource exception it will log it and redirect to home.
if (self::__isResourceException($message))
{
return self::__dismissError();
}
return parent::handleException($e);
}
/**
* This method redirects to home address using CakeResponse Object.
*
* @return mixed
*/
private static function __dismissError()
{
return (new CakeResponse)->header(array(
'Location' => self::$redirectUrl
));
}
}
UPDATE 2:
Will try a small layer over the ExceptionRenderer.
There's not really a point in using a
CakeResponseobject there... it would work if you'd callsend()on it, however with only that one header, there's no advantage over usingheader()directly.That being said, you are however in any case ditching the
Controller.shutdownandDispatcher.afterDispatchevents. They are being dispatched inExceptionRenderer::_shutdown(), and are often used to set response headers (CORS related headers are a good example), so you should figure whether its OK to drop them, or maybe even required.If you need to keep the
shutdownandafterDispatchevents, then you should either fire them on your own, or maybe even use an extendedExceptionRendererthat handles that specific type of exception and sends an empty reponse with your location header added.See also