I would like to show a custom error page when the reporting level is set to 0 and it is a 500 error not a 404. It seems I can't access the error message at all, outside of the default view.
I would like to set a custom layout outside of the normal error layouts. I know if I switch the reporting to level 1 or 2 then it works fine. I want this for production where it is set at 0 and not a 400 error. Is this possible?
$error->getMessage()
Q: I would like to show a custom error page when the reporting level is set to 0 and it is a 500 error
A: You can edit the default error views error400.ctp and also error500.ctp in /app/View/Errors/
Q: I would like to set a custom layout outside of the normal error layouts.
A: If you want to use another (custom) layout you can copy the file CakeErrorController.php from /lib/Cake/Controller/ to /app/Controller/ and add the following line in the function:
function __construct($request = null, $response = null) {
$this->layout = 'your-layout-name'; // add this line in the function
// ...
}
and add the custom layout template file as usual in /app/View/Layouts/, e.g. your-layout-name.ctp
If you want to show data from your app in the error page/layout (eg generate the main menu from the database) you can add more custom code in your error controller as well, e.g.:
// Error controller in /app/Controller/CakeErrorController.php
class CakeErrorController extends AppController {
public $uses = array('MenuCategory'); // load relevant table/model
public function __construct($request = null, $response = null) {
$this->set('mainmenu', $this->MenuCategory->getMenu()); // or find() or whatever
// ...
}
}
Q: How can I keep different error messages in production mode (debug level = 0)?
A According to the documentation "ErrorHandler by default, displays errors when debug > 0, and logs errors when debug = 0." The reason is e.g. that you should not show your public visitors (in production mode) an error message like "Missing Component", because this error is irrelevant and not useful for the visitor (so a 404/500 is responded). These kind of errors are only relevant for development and should be fixed before you go live in production mode.
If you want to change this behaviour you have to set up your own error handling as it is exlained in the book. Please also have a look at the explanation directly in the CakePHP code. You can also create your own exeptions if necessary.
If you have problems in using/creating your own error handler, please start a new question on Stackoverflow with more details: What files have you created (e.g. your error handler and/or exceptions), how is your code looking like, what have you tried to solve the problem... and please give a clear example of what you want to achieve (e.g. in the comments below to the first version of my answer you are talking about special 500 errors - What is triggering these errors and what do you want to response instead of a 500 or what exactly do you want to change...)?
An alternative solution in some situations could also be something like this:
// In your controller
public function moderator_view($id = null) {
// Your error check, in this example the user role
if ( $this->Auth->user('role') != 'moderator' ) {
// Custom error message
$this->Flash->custom('You are not a moderator.');
// Redirect to your your special error page
// In this example got to previous page
return $this->redirect(
$this->referer(
// or go to a default page if no referrer is given
array('controller' => 'articles', 'action' => 'index', 'moderator' => false)
)
);
}
// else show moderator content...
}
Please also have a look at the many other questions to custom error pages in CakePHP ;-)
Related
I am new in Cakephp i develop my whole website but at some point when anyone type my website name like www.example.com/controllername/action it opens correct but anyone type like www.example.com/xyz then it shows error like
Missing Controller
Error: xyzController could not be found.
Error: Create the class xyzController below in file: app/Controller/xyzController.php
<?php
class xyzController extends AppController {
}
Notice: If you want to customize this error message, create app/View/Errors/missing_controller.ctp
Stack Trace
APP/webroot/index.php line 109 → Dispatcher->dispatch(CakeRequest, CakeResponse)
the same process is apply on action like i type www.example.com/controllername/xyz then it shows error like
Notice: If you want to customize this error message, create app/View/Errors/missing_action.ctp
what i do to remove this message if i create that file in view folder then in header footer it shows undefined variable where i dynamically called variable.what i do.please suggest me,thanks in advanced.
Just create the app/View/Errors/missing_action.ctp file in the given location with your custom message and styles. Then in your appController file just write this:
function beforeRender () {
if ($this->name == 'CakeError') {
$this->layout = false;
}
}
Hope this will work for you. :)
If your site users are seeing error messages like this then it implies that you don't have debug set to 0 which it should be in production.
Make sure you have Configure::write('debug', 0); set in app/Config/core.php. Only enable debugging on a staging or local copy of your site otherwise you risk revealing error messages to users on your live site that may lead to vulnerabilities.
With debug set to 0 the errors will only get logged in your app's error.log and the user will be delivered a 404 page. This is correct as a missing Controller is technically an error.
You are getting errors like this because you're using the magic routing setup when you first install CakePHP to help you build your app. It is a good idea to consider explicitly defining all your app routes in routes.php and disabling the default routing behaviour by removing this line from the file:-
require CAKE . 'Config' . DS . 'routes.php';
If you do this you will not get any error messages for pages that do not exist, but you also will not be able to access any page that a route hasn't been defined for. This is not necessarily a bad thing, Beware the Route to Evil is a good read in regards to this.
In my project to catch all the PHP errors I have set up my error handling mechanism as follows:
I have set error_reporting() in index.php file which overrides
anything in the php.ini file
An error handler is set in system/codeigniter/CodeIgniter.php using
set_error_handler - this error handler, _exception_handler, is
found in system/codeigniter/Common.php
The _exception_handler function ignores E_STRICT errors, calls the
show_php_error function From the Exceptions system library if the
severity is that specified by your error_reporting() function in
index.php and logs the error according to whatever you have set up in your config.php file
The handler returns FALSE so after this PHP goes on to handle the
error however it normally would according your error_reporting level
and display_errors setting.
The thing that is puzzling me is that E_ERROR errors i.e. fatal errors don’t seem to be being caught by _exception_handler at all. It’s not just that show_php_error isn’t being called, it looks like the function just isn’t being called for them. This is obviously a problem as it means that they aren’t get handled by show_php_error or logged. For example if I deliberately mistype $this->load->views('foo'); in a controller, the handler doesn’t get called.
Any suggestion about error handling would be much appreciated, thanks!
Now this is a rather big debate:
Whether you should catch the fatal errors or not.
Some say that they are FATAL so you dont know in which condition is the system but I will go with the "try to do the cleanup if the error occured".
In order to catch ALL fatal errors you will need to setup a pre_system hook.
go to application/config/hooks.php and enter
$hook['pre_system'][] = array(
'class' => 'PHPFatalError',
'function' => 'setHandler',
'filename' => 'PHPFatalError.php',
'filepath' => 'hooks'
);
after that go to hooks directory and add your handling of the error:
<?php
class PHPFatalError {
public function setHandler() {
register_shutdown_function('handleShutdown');
}
}
function handleShutdown() {
if (($error = error_get_last())) {
ob_start();
echo "<pre>";
var_dump($error);
echo "</pre>";
$message = ob_get_clean();
sendEmail($message);
ob_start();
echo '{"status":"error","message":"Internal application error!"}';
ob_flush();
exit();
}
}
as you can see we are using the register_shutdown_function to run a function that checks if an error had occured and if it had send it via email to the developer.
This setup is working flawlessly for over 2 years in several CI projects that I have been working with.
I've found this answer under an other question (https://stackoverflow.com/a/3675357), and i think it is also useful for anyone reading this question.
"For codeigniter specific error handling, you can override its 'Exception' library class by creating My_Exception class in your application/libraries folder. Copy original library function signatures into it and put in your code. It will surely work."
Simply you can handle all type of error in one file which is display
your client because of php error or any other error is not good to
display client.
Simply place file Common_Exceptions.php in core folder . Common is my because in config file I have declare $config['subclass_prefix'] = 'Common_';
Copy system\core\Exceptions.php file and paste in core\Common_Excepions file (class Common_Exceptions extends CI_Exceptions) and do your change in this file and call view for your want and display to client when error come.
NOTE: $config['log_threshold'] = 1; enable in config file for errorlog write and after you see what error come.
One more suggestion on view file which is display when error is come there place time so when you see in log then match this time and find which error is come that time
I am looking for a way in which all the errors will be logged automatically with one line of code. If you know Asp.NET, you probably know what I mean like using Application_Error event handler.
I checked PHP Logging framework? question in SO but they all look same, you should log each and every log message manually which means I need to call the log function everywhere I want to log.
What I am looking for not something like this (which is used by KLogger)
require_once 'KLogger.php';
...
$log = new KLogger ( "log.txt" , KLogger::DEBUG );
// Do database work that throws an exception
$log->LogError("An exception was thrown in ThisFunction()");
// Print out some information
$log->LogInfo("Internal Query Time: $time_ms milliseconds");
// Print out the value of some variables
$log->LogDebug("User Count: $User_Count");
You can create your own custom error handler function in PHP and set it as the error handler
something like:
function handle_error($error_level,$error_message)
{
/*
here do what you want...typically log it into db/file/send out
emails based on error level etc..
*/
}
and to set this function as your default error handler for PHP add this line:
set_error_handler("handle_error");
All errors will now be handled by PHP based on what is written inside handle_error
I have been reading the following question here: CakePHP 2.0 - How to make custom error pages?
About creating custom views for exception handling in CakePHP 2.0+ and have been using it as a base to start doing the same in my own application hence starting my own question.
However I'm not following the logic. For example how does the Throw NotFoundException know to call the notFound method in the Errors Controller as I don't see any direct relationship in terms of the naming... Unless I'm missing the point?
In any case I'm looking to add 404, 403, and 401 errors and then be able to create custom views and call them using the exception handler throughout my app.
Can anyone shed more light on this? I'm using the latest version of Cake 2.1
So I have the following code:
App::uses('ExceptionRenderer', 'Error');
class AppExceptionRenderer extends ExceptionRenderer {
public function notFound($error) {
$this->controller->redirect(array('controller' => 'errors', 'action' => 'error404'));
}
}
And I want to replace that redirect with rendering a custom error view:
I've tried:
$this->controller->layout = null;
$this->controller->render('/Errors/error404');
But that just shows a blank page... Can anyone help me out as I don't want to do the redirect and would much rather follow conventions and render actual views with the same url when getting errors.
Update: Also noticed that the custom views ONLY get called when exceptions are manually called in the controller, and not for actual errors such as domain.com/garbageurl or something else... So it doesn't seem to be doing what I thought!
Have a look at these files from core Cake:
Cake/Error/ErrorHandler.php
Cake/Error/ExceptionRenderer.php
Here's what's happening:
ErrorHandler::handleException() is your exception handler. It gets called when an exception is thrown.
ErrorHandler::handleException() calls ExceptionRenderer::__construct() (your custom exception renderer must extend ExceptionRenderer) which parses the name of the Exception that was thrown, and from that, sets $this->method.
ErrorHandler::handleException() then calls ExceptionRenderer::render() which uses call_user_func_array() to call the method whose name is $this->method.
I was just looking for the same thing and could not find a neat way to do this using AppExceptionRenderer. It just won't allow you to have separate error403 and error404 template files.
So I just did this in my /app/View/Errors/error400.ctp file instead...
<? if ($error instanceof ForbiddenException) { ?>
<h4>Whoops! The page you attempted to access
requires permissions that you don't have.</h4>
<? } else { ?>
<h4>Whoops! We couldn't find the page you were looking for, sorry!</h4>
<? } ?>
In production mode (minimal errors), when a controller is not found, Zend gives a 404 page not found error. There are a couple of controllers that I don't want this activated for. Even though they don't exist, I don't want the page not found error activated. Is it possible to somehow block that error and give an empty page. I'm guessing, if at all possible, it has to be done at the plugin level since no controller really exists to handle this.
One possible solution would be to check the request object in your errorAction for controller and/or action that threw the exceptions (for non-existing controllers and actions you could also get their names this way). Based on this you could customize the rest of errorAction. For example:
public function errorAction() {
$errors = $this->_getParam('error_handler');
$whatController = $errors->request->getControllerName();
if ('secretController' == $whatController) {
return $this->_redirect('blankErrorPage');
}
// usual rest of errorAction
}