I have encountered a strange problem with errors in Cake 2 which I have never had in 1.3.
When some exception raised (i.e. NotFoundException) Cake's error handling begins.. By default it instantiates CakeErrorController and does all that stuff (see the source) and.. escapes viewVars. But I have some view vars set in my AppController's beforeRender and I don't want them to be escaped, because they contain html and they are supposed to be rendered in the layout. What is the reason of such behavior? How can I tell Cake not to do that?
Thank you.
Update:
Well. I worked out some solution:
I created Controller/AppErrorController.php:
App::uses('CakeErrorController', 'Controller');
class AppErrorController extends CakeErrorController {
public function beforeRender() {
AppController::beforeRender();
}
}
and Lib/Error/AppExceptionRenderer.php:
App::uses('ExceptionRenderer', 'Error');
class AppExceptionRenderer extends ExceptionRenderer {
protected function _getController($exception) {
App::uses('AppErrorController', 'Controller');
if (!$request = Router::getRequest(false)) {
$request = new CakeRequest();
}
$response = new CakeResponse(array('charset' => Configure::read('App.encoding')));
try {
$controller = new AppErrorController($request, $response);
} catch (Exception $e) {
$controller = new Controller($request, $response);
$controller->viewPath = 'Errors';
}
return $controller;
}
}
And in Config/core.php I set:
Configure::write('Exception', array(
...,
'renderer' => 'AppExceptionRenderer',
...
));
Looks like it works as expected, but is there any more elegant solution?
Thank You.
It's probably also because the CakeErrorController is used for all exceptions -- so the framework can pass any message for any error without worrying about HTML injection or garbled output. I'm assuming it's just about reliable output since Cake docs describe the controller as "[omitting] a few of the normal callbacks to help ensure errors always display". It's a lean, stripped-down controller for a specific purpose.
Unfortunately this means that they've hard-coded the CakeErrorController's
beforeRender
method, so there's no way to turn it off. The only simple options I can think of are hacky...htmlspecialchars_decod()
function to convert escaped text back into unescaped text. (If you wanted to be thorough you would also check the encoding, etc. Basically reverse whath()
did to your string)beforeRender
isn't escaping objects).Fortunately there is a proper workaround provided in the docs and you've already figured it out.
It feels like a lot of work just to get some HTML into your view because it is a lot of work doing it that way. MVC is supposed to help separate your concerns, but you're mangling that separation by creating HTML in your Controller instead of in your View.