PHP custom error page - php

Everyone says that "Enabling errors to be shown" in an active site is bad (due to some security issues).
Now, we have to consider 2 cases:
The site is in debug mode
The site is not in debug mode
Now, for case #1:
We want to see the errors. How?
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 1);
Nothing more simple. Also we can customize an error handler for all errors except Parse and Fatal.
Instead, if the case is #2:
We would like to be able to deactivate the messages:
ini_set('error_reporting', 0);
ini_set('display_errors', 0);
And it's ok. But what about showing users a friendly message such as "Hei man, something is really f**ked up. I don't assure you we are working to fix it, since we are very lazy.".
You should enable errors again and just use the function set_error_handler() and hope that no parse or fatal errors occur. But my first question is:
Question 1: Is that possible to avoid error reporting and have a custom offline page that is loaded when something goes wrong? I mean, is it possible to have ini_set('error_reporting', 0); and ini_set('display_errors', 0); and still be able to tell PHP to load a custom Error page?
And now another:
Question 2: I developed a class that with the power of set_error_handler() logs errors occurred into the database. In this way I can keep track of hack attempts and other cool stuff. (And yes, i'm always sure the DB is accessible since my application shuts down if we cannot connect to the DB). Is this worth something?

Some time ago I created small system that redirects you to error page when fatal error occurs / uncaught exception was thrown. It was possible with assumption, that every request is handled by one file and ends in this file, so by reaching end of this file I'm sure that everything went OK. With this condition I've set up function to redirect on error page and registered it as shutdown function - so it will be called at the end of all requests. Now in this function I check conditions for clean shutdown and if hey are met, I do nothing and output is flushed to the browser, otherwise buffer is cleaned and only header redirecting to error page is sent.
Simplified version of this code:
<?php
function redirect_on_error(){
if(!defined('EVERYTHING_WENT_OK')){
ob_end_clean();
header('Location: error.html');
}
}
register_shutdown_function('redirect_on_error');
ob_start();
include 'some/working/code.php';
echo "Now I'm going to call undefined function or throw something bad";
undefined_function();
throw new Exception('In case undefined function is defined.');
define('EVERYTHING_WENT_OK', TRUE);
exit;

Question 1: Is that possible to avoid error reporting and have a custom offline page that is loaded when something goes wrong?
Unfortunately, I don't think so, at least for fatal errors. However, recent versions of PHP always send a 500 response when that occurs, so, depending on webserver, you may be able to rewrite the response if such thing happens. If your actual server running PHP is behind a reverse proxy, this becomes trivial with Apache.
Question 2: I developed a class that with the power of set_error_handler() logs errors occurred into the database.
Sure, it's always good to log the errors. You already seem to be aware of the limitations of logging errors into the database.

Related

PHP error reporting destination: error log file vs. web page

In the following code, I get the 'AAA' on the web page output (only), while the 'BBB' goes to the error.log file (only).
I want both to go to the error.log file, so the user doesn't see potential errors while I do. How?
<?php
ini_set('display_errors','1');
ini_set('error_log','error.log');
error_reporting(-1); // all
trigger_error('AAA');
error_log('BBB');
?>
(Note: This is similar to http://stackoverflow.com/questions/9921643/how-to-make-provoke-an-php-error-in-php-error-log but not the same.)
Set ini_set('display_errors', 0);
OR
Create your own error handler function and add it before calling trigger_error function with set_error_handler function.
This function can be used for defining your own way of handling errors
during runtime, for example in applications in which you need to do
cleanup of data/files when a critical error happens, or when you need
to trigger an error under certain conditions (using trigger_error()).

What about undefined functions in exception handler callbacks?

Let's suppose I have this piece of code, where I try to make sure all my errors are reported in some way, yet the visitors won't have to see but a nice page apologizing for the situation.
ini_set('display_errors', 'off');
error_reporting(E_ALL);
set_exception_handler('exceptionHandler');
function exceptionHandler($error)
{
// functionWithSyntaxError()
undefinedFunction();
echo $error->getMessage();
}
If I would have functionWithSyntaxError() uncommented, I would see the error about the syntax. I guess that's because the code is not even run and the compiler doesn't care about my exception handler or other directives.
Now, if I comment it back and leave only undefinedFunction(), I wouldn't be able to log the error about the undefined function, either would my code run further. I wouldn't know what happens so I would have to set display_errors ON, in which case I would defy my original purpose of not displaying errors, but reporting them silently.
So, in this case I guess the compiler doesn't check for undefined function as it does with the syntax. What happens in this case? It certainly doesn't continue either. Shouldn't the code go in a loop? What happens under the hood?
I know I have better options to handle errors gracefully, defining a debug mode (where errors will be displayed), for example, but I just want to understand the intricacies of this situation

Ignore warning and carry on

I am running a script where a url parameter is increasing by 1. Every so often, I get the error message below and the script comes to a halt:
Warning: file_get_contents(https://example.com?id=431): failed to open
stream: HTTP request failed! HTTP/1.1 429 Please retry after few
minutes
$i = 1;
while($file = file_get_contents('https://example.com?id='.$i)) {
echo ''.$i.'</br>';
$i++
}
While I know I can use error_reporting(0); to stop the warnings from appearing, my question is as follows: will the script continue running after the hidden warning?
You can, of course, disable error reporting as others have suggested. However, there are two MUCH better solutions.
First, you could use set_error_handler to create a function which converts errors into exceptions (code in Example 1 here: http://php.net/manual/en/class.errorexception.php). Then, you can simply use a try and catch to check to see if an exception has occurred, and handle it appropriately. See here: http://php.net/manual/en/internals2.opcodes.catch.php
Another solution would be to use PHP's cURL library (http://php.net/manual/en/book.curl.php). cURL will let you check if an error has occurred when you make an HTTP request, and you can respond appropriately.
To be clear, since it seems to be OP's only concern: both of these solutions will allow the script to continue running after an error has occurred. They also have the added benefit of allowing OP to create code that makes a predetermined programmatic response to errors rather than just blindly ignoring any and all errors with unknown results (and no indication that they even happened).
Finally, a note that's applicable to this particular situation: HTTP 429 is "too many requests," which makes sense given that OP is placing these requests one after another with no delay. Sleeping (http://php.net/manual/en/function.sleep.php) between HTTP requests would likely eliminate the problem entirely.
This is not something you should use in prod, but try:
error_reporting(E_ERROR | E_PARSE);
I think it is better to check if the file is reachable before trying to read it.
Replace the condition, e.g.:
while($i < 100)
You can try this:
error_reporting(0);
Put this at the top of script
Put this at the top of the script to avoid the warnings and notices.
error_reporting(E_ERROR);
This will still show Fatal run-time errors. These indicate errors that
can not be recovered from, such as a memory allocation problem.
Execution of the script is halted.
To turn of all the errors and warning,
error_reporting(0);

PHP how to trigger user error with trigger_error in an object destructor while the script shuts down?

While implementing some class I've run into a little problem:
If the script ends and destructors are called because the script has finished, I wanted to trigger an error occasionally.
I thought the trigger_error() function would be of use. However, if error_reporting(-1) the triggered error is not send any longer to STDOUT or STDERR - while it is expected to do so (e.g. if not within the __destructor/termination phase of the script, trigger_error works as expected).
If I echo some message out, it will be send to STDOUT (CLI mode).
I now wonder
how I can trigger an error in this phase of the application?
and/or alternatively how can I detect that currently the script is shutting down because it has successfully ended?
Note: I tested connection_status() but it's useless in my case as it's about connection handling only and merely unrelated. I wonder if there is some function that does the same for the scripts execution status (starting, running, exiting).
Simplified Example Code
This is some very reduced example code to illustrate the issue. Naturally is the error only triggered if it makes sense for the object:
<?php
class TriggerTest
{
public function __destruct()
{
trigger_error('You should have missed something.');
}
}
$obj = new TriggerTest;
exit();
The problem is, that trigger_error() gets executed but the error does not appear anywhere.
How about if you force the error reporting to be a certain setting, trigger the error and then set the error reporting back to it's normal form?
Answer: Just do it. I had some misconfiguration for the error handler and therefore it did not work. My fault.
However it's still interesting if there is any function or similar to determine the execution state on shutdown.

PHP turn off errors - in one file only

I am well aware about error_reporting(0); & ini_set('display_errors', "Off"); to make error messages go away.
What would be an appropriate way to do this - for a specific file or part of code only?
Surpressing errors with #'s seems like a bad idea since it apparently slows the code down...
The reason? We have a number of memcached servers in a development LAN that is really unreliable due to the network settings, thereby we are recieving errors multiple times every hour and there's nothing we can do about it except stop using memcache or turning off errors for the whole application, which would be giving us a headache - in the middle of the development stage :)
<?php
// normal code
// error_reporting returns the old error code
$old_error_reporting = error_reporting(0);
// your errorful code
// reset error_reporting to its old value
error_reporting($old_error_reporting);
// normal code
Although it would be a good idea to fix what is actually causing the errors.
You've kind of answered your own question. To do it for a specific file, error_reporting(0); will turn off errors. You can also call it multiple times in a script, I think.
You can also use php exceptions to 'catch' errors over a block of code. For example:
try {
// code to ignore errors for here
} catch {
// you can output a custom error here, but putting nothing here will effectively mean errors are ignored for the try block
}
The script will continue running past the try block, even if there is an error within it. See the PHP Manual Entry for more information.
You can change the error reporting level during runtime:
<?
error_reporting(E_ALL);
... some code ....
error_reporting(0);
... some more code ....
error_reporting(E_ALL);
I know of no other way but I can't think of a case where this wouldn't be sufficient. Can you?
That's really a long time ago but someone like me would maybe use my answer.
When i need to do this kind of stuff, i just put # before the variable in order to NOT display the errors coming from this variable.
example:
switch(#$var!="e") {
....
}

Categories