I have a custom error handler that's supposed to log errors to a database, but for some reason this error always shows up in the database. Every time a page is loaded "0 in on line 0", where the first 0 is the error level, in whatever file, since it's not provided, on line 0. This is odd because I've never seen this until now. The error handler is below;
public function fatalErrHandlr(){
$errstrArr = error_get_last();
$errno = mysqli_real_escape_string($this->dbc, trim($errstrArr['type']));
$errstr = mysqli_real_escape_string($this->dbc, trim($errstrArr['message']));
$errfile = mysqli_real_escape_string($this->dbc, trim($errstrArr['file']));
$errline = mysqli_real_escape_string($this->dbc, trim($errstrArr['line']));
$query = "INSERT INTO `err` (`errno`, `errstr`, `errfile`, `errline`) VALUES ('$errno', '$errstr', '$errfile', '$errline')";
mysqli_query($this->dbc, $query);
//var_dump(mysqli_error($this->dbc));
echo("<b>There was an error. Check the database.</b>");
//return true;
}
The error handler is configured with:
register_shutdown_function(array($core, 'fatalErrHandlr'));
register_shutdown_function doesn't configure an error handler, it sets a function to run whenever the script finishes. So you're getting a log message every time the script runs, whether or not it got an error. The correction function is set_error_handler. It passes the details as arguments to the callback, so you don't need to use error_get_last
public function fatalErrHandlr($errno, $errstr, $errfile, $errline){
$query = $this->dbc->prepare("INSERT INTO `err` (`errno`, `errstr`, `errfile`, `errline`) VALUES (?, ?, ?, ?)");
$query->bind_param('ssss', $errno, $errstr, $errfile, $errline)
$query->execute();
//var_dump(mysqli_error($this->dbc));
echo("<b>There was an error. Check the database.</b>");
//return true;
}
Related
I am using the amazon.com products API. The call is GetMatchingProductForId. When I type as single value into the call, it works. When I input a large file to my program it works, but I occasionally get a fatal error:
Fatal Error:Can Only Throw Objects in J:/filepath/client.php on line 1003.
I have no idea what the possible error is. When i contacted amazon developer support they said they would investigate the issue.
The problem could possibly be the user input because I ran my program yesterday and was able to get 2797 files in response, but eventually received the same error. When i ran my program for the first time during testing, there was no problem at all. If anyone has knowledge of this error and could explain just the error, I would greatly appreciate it.
Client.php lines 992 - 1004:
for (;;) {
$response = $this->_httpPost($parameters);
$status = $response['Status'];
if ($status == 200) {
return array('ResponseBody' => $response['ResponseBody'],
'ResponseHeaderMetadata' => $response['ResponseHeaderMetadata']);
}
if ($status == 500 && $this->_pauseOnRetry(++$retries)) {
continue;
}
throw $this->_reportAnyErrors($response['ResponseBody'],
$status, $response['ResponseHeaderMetadata']);
}
I did not edit any of this code. This came from developer.amazonservices.com
_reportAnyErrors Function :
private function _reportAnyErrors($responseBody, $status, $responseHeaderMetadata, Exception $e = null)
{
$exProps = array();
$exProps["StatusCode"] = $status;
$exProps["ResponseHeaderMetadata"] = $responseHeaderMetadata;
libxml_use_internal_errors(true); // Silence XML parsing errors
$xmlBody = simplexml_load_string($responseBody);
if ($xmlBody !== false) { // Check XML loaded without errors
$exProps["XML"] = $responseBody;
$exProps["ErrorCode"] = $xmlBody->Error->Code;
$exProps["Message"] = $xmlBody->Error->Message;
$exProps["ErrorType"] = !empty($xmlBody->Error->Type) ? $xmlBody->Error->Type : "Unknown";
$exProps["RequestId"] = !empty($xmlBody->RequestID) ? $xmlBody->RequestID : $xmlBody->RequestId; // 'd' in RequestId is sometimes capitalized
} else { // We got bad XML in response, just throw a generic exception
$exProps["Message"] = "Internal Error";
continue;
}
}
Values :
20373001862
20373002678
20373002685
20373002937
20373003002
20373003583
20373003644
20373003651
20373003675
20373003682
20373003781
20373003811
20373003828
20373003835
20373003842
20373003859
20373003866
20373003873
20373003880
20373003897
20373003903
20373005006
With these values it crashed on the third file which would be the 20th value.
I am getting the below error in one of the file in Production, where the function is defined twice. I tried to recreate the issue, getting in a different file.
Fatal error: Cannot redeclare foo() (previously declared in
/home/content/45/8989001/html/test/test.php:5) in
/home/content/45/8989001/html/test/test.php on line 10
To suppress this error, its advised to make an entry to php.ini file, but I don't have access to it as its shared hosting.
Alternatively, its suggested to make an entry to existing php file inside the <?php ?> tags. I did the below change.
error_reporting(0); // This is not working, still error is displayed
error_reporting(E_NONE); // This is not working, still error is displayed
ini_set('display_errors', 0); // This is not working, still error is displayed
My complete code,
<?php
function foo() {
return "foo";
}
function foo() {
return "foo";
}
// error_reporting(0); // This is not working, still error is displayed
// error_reporting(E_NONE); // This is not working, still error is displayed
ini_set ( 'display_errors', 0 ); // This is not working, still error is displayed
echo "hello";
?>
Problem: How to suppress this error in Production, instead log to some file. or at-least suppress the error?
Note: The error is fixed in prod, but how to suppress it to avoid user seeing error in some other file next time
Update1:
After the below change too, the error is the same.
<?php
ini_set ( 'display_errors', 0 );
function foo() {
return "foo";
}
function foo() {
return "foo";
}
// error_reporting(0); // This is not working, still error is displayed
// error_reporting(E_NONE); // This is not working, still error is displayed
// ini_set ( 'display_errors', 0 ); // This is not working, still error is displayed
echo "hello";
?>
Update2:
<?php
register_shutdown_function( "fatal_handler" );
function fatal_handler() {
echo "inside fatal_handler";
$errfile = "test";
$errstr = "shutdown this test";
$errno = E_CORE_ERROR;
$errline = 0;
$error = error_get_last();
echo $error;
if( $error !== NULL) {
$errno = $error["type"];
$errfile = $error["file"];
$errline = $error["line"];
$errstr = $error["message"];
$newline = "\r\n";
define ( 'senderName', 'Error' );
define ( 'senderEmail', 'admin#abc.com' );
$headers = "From: " . senderName . " <" . senderEmail . "\r\n";
$subject_admin = 'Error-Fix it';
$body_admin = "Dear Admin, $newline$newline An error occured $newline" . "error number : " . $errno . $newline . " error file : $errfile" . $newline . "error line :" . $errline . $newline . "error string : $errstr" . $newline;
$body_footer = " **** This is an an auto-generated mail. kindly do not reply to this mail. Thank You. ****" . $newline . $newline;
$body_admin = $body_admin . $newline . $newline . $newline . $body_footer;
$to_admin1 = 'mymail#gmail.com';
mail ( $to_admin1, $subject_admin, $body_admin, $headers );
//error_mail(format_error( $errno, $errstr, $errfile, $errline));
}
}
function foo() {
return "foo";
}
function foo() {
return "foo";
}
// error_reporting(0); // This is not working, still error is displayed
// error_reporting(E_NONE); // This is not working, still error is displayed
// ini_set ( 'display_errors', 0 ); // This is not working, still error is displayed
echo "hello";
?>
update 3
Still getting same error
<?php
register_shutdown_function ( "fatal_handler" );
function fatal_handler() {
echo 'YAY IT WORKED';
}
function foo() {
return "foo";
}
function foo() {
return "foo";
}
// error_reporting(0); // This is not working, still error is displayed
// error_reporting(E_NONE); // This is not working, still error is displayed
// ini_set ( 'display_errors', 0 ); // This is not working, still error is displayed
echo "hello";
?>
Update4
<?php
//error_reporting(0);
function fatalErrorHandler() {
echo 'YAY IT WORKED';
}
# Registering shutdown function
register_shutdown_function('fatalErrorHandler');
// let force a Fatal error -- function does not exist
functiontest();
echo "hello";
?>
<!--
output:
Fatal error: Call to undefined function functiontest() in ...test2.php on line 12
YAY IT WORKED -->
<?php
error_reporting(0);
function fatalErrorHandler() {
echo 'YAY IT WORKED';
}
# Registering shutdown function
register_shutdown_function('fatalErrorHandler');
// let force a Fatal error -- function does not exist
functiontest();
echo "hello";
?>
<!-- output:
YAY IT WORKED -->
Final update:
This resolved my intermediate question
register_shutdown_function is not getting called
If I were you I would call my host and ask them to make the changes to my phpini. They may have special things setup.
Now you should never just hide errors. You send yourself an email and fix right away. The error you are trying to surpress is fatal and the script will no longer run, so hiding it only results in a blank page, the user stkill cannot continue.
It is a fatal error and you cannot recover from it. The way to hide fatal error properly in my opinion is to create your own error handler function.
And you would use something like this to catch the fatal errors.
http://php.net/manual/en/function.register-shutdown-function.php
The function needs to be on every page in order to catth the error. I have a error.php that I require in my db class, which is on every page.
//This function gets called every time your script shutsdown
register_shutdown_function( "fatal_handler" );
function fatal_handler() {
$errfile = "unknown file";
$errstr = "shutdown";
$errno = E_CORE_ERROR;
$errline = 0;
$error = error_get_last();
if( $error !== NULL) {
$errno = $error["type"];
$errfile = $error["file"];
$errline = $error["line"];
$errstr = $error["message"];
//send error email
error_mail(format_error( $errno, $errstr, $errfile, $errline));
}
}
UPDATE
**OP said the function is not being called. **
The above should work.
Here is basically what I use in production, it should tottally work.
ON_SCREEN_ERRORS and SEND_ERROR_EMAIL are my own config constants for development.
//Set error handler function (See function below)
set_error_handler("StandardErrorHandler");
/**
* Will take an error string and if ON_SCREEN_SQL_ERRORS is set to on, it will display the error on the screen with the SQL in a readable format and
* if SEND_SQL_ERROR_EMAILS is set to on, it will dendthe error email with the SQL in a readable format.
*
* PHP will pass these parameters automatically on error.
*
* #param string $errno The error type code.
* #param string $errstr The error string.
* #param string $errfile The file that the error occured in.
* #param string $errline The line number that the error occured.
*/
function StandardErrorHandler($errno, $errstr, $errfile, $errline) {
$Err = $errstr.'<br />'.GetErrorType($errno).'on line '.$errline.' in '.$errfile.'<br />';
if (ON_SCREEN_ERRORS===TRUE)
{
err($Err);
}
if ($errno =='256' and SEND_ERROR_EMAILS === TRUE)
{
$Path = "http://". $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
// Custom error function
gfErrEmail($Err, $Path, 'SQL Error');
}
}
//Set the Fatal Error Handler function (See function below)
register_shutdown_function("FatalErrorHandler");
/**
* This function gets called on script shutdown, it will check if the last error is a fatal error. You cannot catch fatal errors,
* but using this function we will be notified about it and be able to fix it.
* If error is fatal, and if ON_SCREEN_FATAL_ERRORS is set to ON, this function will display the fatal error on the screen.
* If error is fatal, and if SEND_FATAL_ERROR_EMAILS is set to ON, this function will send error email.
*
*/
function FatalErrorHandler() {
$error = error_get_last();
if($error !== NULL) {
//check if error is of fatal, compliler or other non recoverable error types
if ($error["type"] =='1' || $error["type"] =='4' || $error["type"] =='16' || $error["type"] =='64' || $error["type"] =='4096')
{
$errno = GetErrorType($error["type"]);
$errfile = $error["file"];
$errline = $error["line"];
$errstr = $error["message"];
$Err = '<strong>'.$errno.'<br/></strong>'.$errstr.'<br />'.$errno.' on line '.$errline.' in '.$errfile.'<br />';
if (ON_SCREEN_ERRORS===TRUE)
{
err($Err);
}
if (SEND_ERROR_EMAILS === TRUE)
{
$Path = 'http://'. $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
//Custom function
gfErrEmail($Err, $Path, $errno);
}
}
}
}
/**
* This function receives the error code and returns the specified string.
* The return strings are what the error message will display.
*
* #return string The error title
*/
function GetErrorType($Type)
{
switch($Type)
{
case 1:
// 'E_ERROR';
return 'Fatal Error ';
case 2:
// 'E_WARNING';
return 'Warning ';
case 4:
// 'E_PARSE';
return 'Compile Time Parse Error ';
case 8:
// 'E_NOTICE';
return 'Notice ';
case 16:
// 'E_CORE_ERROR';
return 'Fatal Start up Error ';
case 32:
// 'E_CORE_WARNING';
return 'Start Up Warning ';
case 64:
//'E_COMPILE_ERROR';
return 'Fatal Compile Time Error ';
case 128:
// 'E_COMPILE_WARNING';
return 'Compile Time Warning ';
case 256 :
// 'E_USER_ERROR' - USED FOR SQL ERRORS - DO NOT USE THIS ERROR CODE to TRIGGER_ERROR()
return 'SQL Error ';
case 512:
// 'E_USER_WARNING';
return 'Warning - Thrown using trigger_error() ';
case 1024:
// 'E_USER_NOTICE';
return 'Notice - Thrown using trigger_error() ';
case 2048:
// 'E_STRICT';
return 'Strict Error (PHP suggest changes to your code which will ensure the best interoperability and forward compatibility of your code.) ';
case 4096:
// 'E_RECOVERABLE_ERROR';
return 'Catchable Fatal Error (This error can be caught, use a Try Catch) ';
case 8192:
// 'E_DEPRECATED';
return 'Warns you of depreciated code that will not work in future versions of PHP. ';
case 16384:
// 'E_USER_DEPRECATED';
return 'Programmer Triggered Error - Thrown using trigger_error() ';
}
return "Error Type Undefined ";
}
I have this piece of code:
try
{
foreach($obj_c->getGalleries($db_conn1) as $gallery)
{
$gallery->Save($db_conn1);
}
$k = 0;
$testing_the_exception = 15/$k;
//settin status to 1...
$obj_c->set_exec_status(3, 1, $db_conn1);
}
catch (Exception $e)
{
//settin status to 3...
$obj_c->set_exec_status(3, 3, $db_conn1);
echo 'Caught exception: ', $e->getMessage(), "\n";
}
unset($obj_c);
The fact is that it should be entering into the catch part, because of the division by zero exception, but instead it is just popping a warning and continuing to set status to 1. Is this the expected behaviour? Thanks a lot in advance.
This is more a a wholesale solution. Set up error reporting to throw exceptions:
<?php
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");
/* Trigger exception */
strpos();
?>
This is an example from the set_error_handler documentation on php.net
Thats because division by 0 is a warning in php and not an exception. The best way to catch this is to test for it and throw your own exception.
if($k == 0)
throw new Exception("Division by zero");
$testing_the_exception = 15/$k;
I am aware of the set_error_handler function.. But I am wondering if it's possible to set a custom error handler for certain user defined functions? Example.
function ArrayToString ($Array){
if (!is_array($Array)){
trigger_error("Not Array", Not_Array); // I know this is invalid syntax but an example
}
return implode (" ",$Array);
}
Then something like:
set_handler_Not_Array(){
//Format with some CSS
echo "The Argument supplied within ".$errline." <br> Inside: ".$errfile." Is not a valid Array";
exit;
}
Is a solution like this possible? Or would I do I have to resort to the current error handling that is in use:
function Error_Handler($errno, $errstr,$error_file,$error_line)
{
$MySQLCheck = "mysql_connect()"; // String to search for
$MySQL = strpos($errstr, $MySQLCheck); // Looks inside the $errstr for the string $MySQLCheck
if ($MySQL !== false) // if Contains the $MySQLCheck
{
unset($errstr); // Unsets the current error message (which usually states username#host
$errstr = "Can Not Connect To Database"; // Changes the error message to something thatdoes not give away username or host.
}
$UndefinedIndex = "Undefined index:"; // String to search for
$Index = strpos($errstr, $UndefinedIndex); // Searches $errstr for the String listed above
if ($Index !== false) // If contains the $UndefinedIndex
{
$errstrbkup = $errstr; // Saves $errstr to another variable before the $errstr is changes
$str = str_replace("Undefined index:", "", $errstrbkup); // replaces "Undefined Index:" with nothing
$errstr = "A Button Does not Seem To Be Handled Correctly! <br> <b>Button Name:</b> $str "; // Changes the $errstr to a new message
}
$UndefinedIndex = "Undefined variable:"; // String to search for
$Variable = strpos($errstr, $UndefinedIndex); // Searches $errstr for the String listed above
if ($Variable !== false) // If contains the $UndefinedIndex
{
$errstrbkup = $errstr; // Saves $errstr to another variable before the $errstr is changes
$str = str_replace("Undefined variable:", "", $errstrbkup); // replaces "Undefined Index:" with nothing
$errstr = "A Variable Does Not Seem To Be Handled. Check $str"; // Changes the $errstr to a new message
}
$ErrorFile = str_replace("/home/u394942373/public_html/", "", $error_file); // Removes the /var/www from showing in the error
// remove the full path up to the file root if detected
echo
"Opps, It Seems An error Has Been Encountered <br>
Technical Information Listed Below: <br>
<br><br><br>
<b>Error Message:</b> $errstr <br>
<b>File Causing Error:</b> $ErrorFile<br>
<b>Line:</b> $error_line <br>
A Member Of The Technical Department Has Been Notified And Will Fix This Error When Available.
";
die();
}
//set error handler
set_error_handler("Error_Handler");
The reason for this, is because my line manager wishes to have a custom error handler for certain types of error messages... Or for every new error thrown would we still have the be modifying the current error handler
m maintaining a project, that has to be compatible through PHP 4.X to 5.2. The project as several errors wich are not very well handled.
What I want to do is redirect user to a "nice" error page, and log the error in the database. In order to keep track of the user, the file, and the error message. Here is what I've tried so far:
set_error_handler("myErrorHandler");
/**
*My function to handle errors
*/
function myErrorHandler( $errno , $errstr , $errfile="nofile" , $errline=0 , $errcontextArray=NULL ){
session_start();
if (!isset($errno)|!isset($errstr)) {
exit(0);
}
if (!mysql_ping()) {
require '../Connection/databaseinfo.php';
}
$id_user = $_SESSION['ident'];
$errstr = GetSQLValueString($errstr, "text");
$errfile = GetSQLValueString($errfile, "text");
$errline = GetSQLValueString($errline, "int");
$sql = "insert into error_history
(id_user, message, file, line)
values ($id_user, $errstr, $errfile, $errline)";
mysql_query($sql) or die (mysql_error());
// header("location:error.php"); ---> I can't (see comment below)
echo "<script type='text/javascript'> window.location.href='error.php';</script>";//Redirection dégueulasse //TODO: trouver mieux
return true;
}
Why not header()? Because the error can be triggered anywhere in a page, and thus, having the headers already sent.
Why not header() along with obstart(), ob_flush()? Because there are lot of pages already in production, and I can't modify them all.
My questions are:
Am I doing it wrong?
Is there a better way to handle the
redirection?
This is how to handle fatal errors in php 5.2:
<?php
register_shutdown_function('shutdownFunction');
function shutDownFunction() {
$error = error_get_last();
if($error['type'] >= 1){
mail('cc#cc.de', 'Error: XY',"Error msg:"."Server Error:".implode("\n", $error));
}
}
?>