I need to catch some warnings being thrown from some php native functions and then handle them.
Specifically:
array dns_get_record ( string $hostnam
Be careful with the @
operator - while it suppresses warnings it also suppresses fatal errors. I spent a lot of time debugging a problem in a system where someone had written @mysql_query( '...' )
and the problem was that mysql support was not loaded into PHP and it threw a silent fatal error. It will be safe for those things that are part of the PHP core but please use it with care.
bob@mypc:~$ php -a
Interactive shell
php > echo @something(); // this will just silently die...
No further output - good luck debugging this!
bob@mypc:~$ php -a
Interactive shell
php > echo something(); // lets try it again but don't suppress the error
PHP Fatal error: Call to undefined function something() in php shell code on line 1
PHP Stack trace:
PHP 1. {main}() php shell code:0
bob@mypc:~$
This time we can see why it failed.
FolderStructure
index.php //Script File
logs //Folder for log Every warning and Errors
CustomException.php //Custom exception File
CustomException.php
/**
* Custom error handler
*/
function handleError($code, $description, $file = null, $line = null, $context = null) {
$displayErrors = ini_get("display_errors");;
$displayErrors = strtolower($displayErrors);
if (error_reporting() === 0 || $displayErrors === "on") {
return false;
}
list($error, $log) = mapErrorCode($code);
$data = array(
'timestamp' => date("Y-m-d H:i:s:u", time()),
'level' => $log,
'code' => $code,
'type' => $error,
'description' => $description,
'file' => $file,
'line' => $line,
'context' => $context,
'path' => $file,
'message' => $error . ' (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']'
);
$data = array_map('htmlentities',$data);
return fileLog(json_encode($data));
}
/**
* This method is used to write data in file
* @param mixed $logData
* @param string $fileName
* @return boolean
*/
function fileLog($logData, $fileName = ERROR_LOG_FILE) {
$fh = fopen($fileName, 'a+');
if (is_array($logData)) {
$logData = print_r($logData, 1);
}
$status = fwrite($fh, $logData . "\n");
fclose($fh);
// $file = file_get_contents($filename);
// $content = '[' . $file .']';
// file_put_contents($content);
return ($status) ? true : false;
}
/**
* Map an error code into an Error word, and log location.
*
* @param int $code Error code to map
* @return array Array of error word, and log location.
*/
function mapErrorCode($code) {
$error = $log = null;
switch ($code) {
case E_PARSE:
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
$error = 'Fatal Error';
$log = LOG_ERR;
break;
case E_WARNING:
case E_USER_WARNING:
case E_COMPILE_WARNING:
case E_RECOVERABLE_ERROR:
$error = 'Warning';
$log = LOG_WARNING;
break;
case E_NOTICE:
case E_USER_NOTICE:
$error = 'Notice';
$log = LOG_NOTICE;
break;
case E_STRICT:
$error = 'Strict';
$log = LOG_NOTICE;
break;
case E_DEPRECATED:
case E_USER_DEPRECATED:
$error = 'Deprecated';
$log = LOG_NOTICE;
break;
default :
break;
}
return array($error, $log);
}
//calling custom error handler
set_error_handler("handleError");
just include above file into your script file like this
index.php
error_reporting(E_ALL);
ini_set('display_errors', 'off');
define('ERROR_LOG_FILE', 'logs/app_errors.log');
include_once 'CustomException.php';
echo $a; // here undefined variable warning will be logged into logs/app_errors.log
try checking whether it returns some boolean value then you can simply put it as a condition. I encountered this with the oci_execute(...) which was returning some violation with my unique keys.
ex.
oci_parse($res, "[oracle pl/sql]");
if(oci_execute){
...do something
}
I would only recommend using @ to suppress warnings when it's a straight forward operation (e.g. $prop = @($high/($width - $depth)); to skip division by zero warnings). However in most cases it's better to handle.
I wanted to try/catch a warning, but at the same time keep the usual warning/error logging (e.g. in /var/log/apache2/error.log
); for which the handler has to return false
. However, since the "throw new..." statement basically interrupts the execution, one then has to do the "wrap in function" trick, also discussed in:
Is there a static way to throw exception in php
Or, in brief:
function throwErrorException($errstr = null,$code = null, $errno = null, $errfile = null, $errline = null) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
function warning_handler($errno, $errstr, $errfile, $errline, array $errcontext) {
return false && throwErrorException($errstr, 0, $errno, $errfile, $errline);
# error_log("AAA"); # will never run after throw
/* Do execute PHP internal error handler */
# return false; # will never run after throw
}
...
set_error_handler('warning_handler', E_WARNING);
...
try {
mkdir($path, 0777, true);
} catch (Exception $e) {
echo $e->getMessage();
// ...
}
EDIT: after closer inspection, it turns out it doesn't work: the "return false && throwErrorException ...
" will, basically, not throw the exception, and just log in the error log; removing the "false &&
" part, as in "return throwErrorException ...
", will make the exception throwing work, but will then not log in the error_log... I'd still keep this posted, though, as I haven't seen this behavior documented elsewhere.
If dns_get_record()
fails, it should return FALSE
, so you can suppress the warning with @
and then check the return value.