I know this is a weird on, but in my code, i have development mode errors, and production mode errors. This is the function i have:
private function error($message, $mysql_error = null){
if( DEVELOPMENT_MODE ){
$exp = new Exception();
$trace = $exp -> getTrace();
array_shift( $trace ); // removes this functions from trace
$data["Error Mg"] = $message;
$data["MySQL Er"] = ( is_null ( $mysql_error ) ) ? "" : $mysql_error;
array_unshift($trace, $data );
fkill( $trace ); // formats array and then dies
}
else{
throw new Exception ( $data );
}
}
I wrote this function in my database class, so that if an error happens, I don't have to provide the check if we're in development mode or not!
So I thought I could externalise the re-usable code. However, because I'm throwing an exception from this function, I'm basically just using a function, that will return a thrown error. Pretty useless in production mode.
I would have to do this every time i want to use it:
try{
$this -> error( "Invalid Link After Connect.", mysql_error () );
} catch ( Exception $exp ){
throw $exp;
}
RATHER THAN JUST
$this -> error( "Invalid Link After Connect.", mysql_error () );
so to avoid writing a try ... catch block for every error function I want to call... is there any way to throw the exception 2 levels up?
An exception will automatically travel up the call chain until it reaches the highest level. If it's not caught there, program execution terminates due to an uncaught exception. The whole point of exceptions is to be able to have errors bubble up. You don't need to throw harder or do anything special to "throw it up 2 levels", that's what it does by definition.
Just omit the try/catch block. Exceptions automatically propagate up as far as they can until something catches them; you don't need to explicitly re-throw them at every level of the call stack.
This...
try{
$this -> error( "Invalid Link After Connect.", mysql_error () );
} catch ( Exception $exp ){
throw $exp;
}
is exactly equivalent to this:
$this -> error( "Invalid Link After Connect.", mysql_error () );
Use Multiple catch Blocks
use admin table which has field
Mode Value
0 Production
1 Debug
the first catch which matches the exception is executed
Example
try {
if (!$bDBConnection && $row['mode'] ==0 ) {
throw new Produciton_DBException("Problem with Database");
}
else
{
throw new Debug_DBException("Problem with Database");
}
}
catch(Produciton_DBException $e)
{
// display suitable error messages
}
catch(Debug_DBException $ex)
{
// Exception falls through until a match is found
}
Related
I have code like this:
try {
$providerError = false;
$providerErrorMessage = null;
$nbg_xml_url = "http://www.somesite.com/rss.php";
$xml_content = file_get_contents($nbg_xml_url);
// ... some code stuff
} catch (Exception $e) {
$providerError = true;
$providerErrorMessage = $e -> getMessage();
$usd = 1;
$rate = null;
$gel = null;
} finally {
// .. Write in db
}`
and problem is that, when file_get_contents can not read url (may be site not responding or something like this..) my code writes error: failed to open stream: HTTP request failed! and execution goes direct to finally block bypass catch block without entering in it..
any ideas?
You can set an empty error handler to prevent the warning and afterward throw a custom exception in case of failure. In this case I would write a custom file_get_content like so:
function get_file_contents($url) {
$xml_content = file_get_contents($url);
if(!$xml_content) {
throw new Exception('file_get_contents failed');
}
return $xml_content;
}
and would use it in your block:
set_error_handler(function() { /* ignore errors */ });
try {
$providerError = false;
$providerErrorMessage = null;
$nbg_xml_url = "http://www.somesite.com/rss.php";
$xml_content = get_file_contents($nbg_xml_url); //<----------
// ... some code stuff
} catch (Exception $e) {
$providerError = true;
$providerErrorMessage = $e -> getMessage();
$usd = 1;
$rate = null;
$gel = null;
} finally {
// .. Write in db
}
Then remember to restore the error handler calling:
restore_error_handler();
Note that when using your own error handler it will bypass the
error_reporting
setting and all errors included notices, warnings, etc., will be passed to it.
$xml_content = file_get_contents($nbg_xml_url);
The function file_get_contents does not throw an exception. Thus an exception will not be thrown if as you say the file is not found.
From the docs:
An E_WARNING level error is generated if filename cannot be found...
This function returns the read data or FALSE on failure. So you could check if $xml_content is FALSE ($xml_content === false) and proceed accordingly.
This is a php code for catching any error or exception.
Throwable is the base interface for any object that can be thrown via a throw statement, including Error and Exception.
This will catch fatal errors too. Without throwable it will not catch fatal errors.
try {
// Code that may throw an Exception or Error.
} catch (Throwable $t) {
// Executed only in PHP 7, will not match in PHP 5.x
} catch (Exception $e) {
// Executed only in PHP 5.x, will not be reached in PHP 7
}
How do i catch (custom)exceptions (with custom exception handler) that i have thrown in custom shutdown function ? I am not using any framework.
Example:
register_shutdown_function( 'shutdownFunction');
set_exception_handler( 'exceptionHandler');
function exceptionHandler(Exception $exception)
{
// handle and log exception for later debugging...
}
function shutdownFunction()
{
// something is not going right...
if (someVariable != someValue)
throw new RuntimeException('blah...'); // WILL NOT be caught by exception handler
}
// somewhere else in the code...
throw new Exception('something...'); // WILL be caught by exception handler (but not in shutdown function)
The script is using exceptions to communicate that it encountered an error during execution ie. unexpected variable passed to function, database failed to insert row etc...
You simply cannot do this in php.
The register_shutdown_function callback is the last thing that happens in your PHP application. Trying to throw an exception in there will not do anything but invoke a standard php handler. There isn't much to be found on the web regarding these inner workings.
However, I created my own solution for directing it to a single function.
set_exception_handler and register_shutdown_functionare very different functions:
set_exception_handler receives a single argument Exception
register_shutdown_function receives no arguments by default
I've made it so that the set_exception_handler (which receives $exception as argument) sets a property which I can use in the register_shutdown_function.
$lastException = null;
set_exception_handler(function ($e) use (&$lastException) {
$lastException = $e;
});
register_shutdown_function(function() use(&$lastException) {
if($error = error_get_last()) {
$lastException = new \ErrorException($error['message'], $error['type'], 1, $error['file'], $error['line']);
}
if($lastException) {
if (APPLICATION_ENV === 'production') {
Sentry\captureException($lastException);
} else {
var_dump($lastException);
}
}
});
I have no clue if this is a good way to solve the issue, but it allowed me to catch require unexisting_phpfile1389.php errors (Fatal) and regular throw \Exception()s in the same function.
Trying to throw an exception inside the shutdown handler will result in the following exception (how ironic):
( ! ) Fatal error: Uncaught Error: Can only throw objects in
C:...\index.php on line 34
( ! ) Error: Can only throw objects in
C:...\index.php on line 34
You can just wrap the body of your shutdownFunction with
function shutdownFunction()
try {
...
} catch (\Exception $e) {
// do something
}
}
and you will catch all exceptions becase Exception is the base class for all of them
It's quite simple:
function exception_handler (Exception $e) {
if ($e instanceof DBException)
error_handler (['query' => $e->getQuery ()]); // Your actions with your custom Exception object
}
function error_handler ($error) {
if (isset ($error['query']))
echo $error['query'];
else
// Another errors
}
set_error_handler ('error_handler', E_ALL);
set_exception_handler ('exception_handler');
I am using this script here and it does not always want to connect to the server I set it to. When it doesn't, it'll show an error "Failed to receive status". I'm wondering how can I test to see if this happens and put it into an if statement?
For example:
if (isError) return false;
Here is the part which checks for the error or not in the script:
if( !$Data )
{
throw new MinecraftQueryException( "Failed to receive status." );
}
Just use try ... catch block. But make sure you are logging the exception message. It'll be helpful for future investigation.
try
{
$Query = new MinecraftQuery( );
// .. do mine craft connection
$Query->Connect( '...', 25565 );
print_r( $Query->GetInfo( ) );
} catch(MinecraftQueryException $mqe){
// log $mq->getMessage() for future investigation
return false;
}
You'll want to surround the Connect call inside a try/catch block in order to catch the exception, and then put the failure code inside the catch block. You can read more about exceptions in the PHP manual:
try {
$query->Connect();
} catch(MinecraftQueryException $exception) {
return false;
}
I know this is a weird on, but in my code, i have development mode errors, and production mode errors. This is the function i have:
private function error($message, $mysql_error = null){
if( DEVELOPMENT_MODE ){
$exp = new Exception();
$trace = $exp -> getTrace();
array_shift( $trace ); // removes this functions from trace
$data["Error Mg"] = $message;
$data["MySQL Er"] = ( is_null ( $mysql_error ) ) ? "" : $mysql_error;
array_unshift($trace, $data );
fkill( $trace ); // formats array and then dies
}
else{
throw new Exception ( $data );
}
}
I wrote this function in my database class, so that if an error happens, I don't have to provide the check if we're in development mode or not!
So I thought I could externalise the re-usable code. However, because I'm throwing an exception from this function, I'm basically just using a function, that will return a thrown error. Pretty useless in production mode.
I would have to do this every time i want to use it:
try{
$this -> error( "Invalid Link After Connect.", mysql_error () );
} catch ( Exception $exp ){
throw $exp;
}
RATHER THAN JUST
$this -> error( "Invalid Link After Connect.", mysql_error () );
so to avoid writing a try ... catch block for every error function I want to call... is there any way to throw the exception 2 levels up?
An exception will automatically travel up the call chain until it reaches the highest level. If it's not caught there, program execution terminates due to an uncaught exception. The whole point of exceptions is to be able to have errors bubble up. You don't need to throw harder or do anything special to "throw it up 2 levels", that's what it does by definition.
Just omit the try/catch block. Exceptions automatically propagate up as far as they can until something catches them; you don't need to explicitly re-throw them at every level of the call stack.
This...
try{
$this -> error( "Invalid Link After Connect.", mysql_error () );
} catch ( Exception $exp ){
throw $exp;
}
is exactly equivalent to this:
$this -> error( "Invalid Link After Connect.", mysql_error () );
Use Multiple catch Blocks
use admin table which has field
Mode Value
0 Production
1 Debug
the first catch which matches the exception is executed
Example
try {
if (!$bDBConnection && $row['mode'] ==0 ) {
throw new Produciton_DBException("Problem with Database");
}
else
{
throw new Debug_DBException("Problem with Database");
}
}
catch(Produciton_DBException $e)
{
// display suitable error messages
}
catch(Debug_DBException $ex)
{
// Exception falls through until a match is found
}
basically i have a custom exception handler. When i handle an exception, i just want it to echo the message and continue the script. But after my method handles the exception, the script doesnt continue.
Is this a behaviour of php or is my exception handler doing something wrong?
This is a behavior of php. This differs from set_error_handler() in that, according to the manual on set_exception_handler(), Execution will stop after the exception_handler is called. Therefore, ensure you catch all exceptions, letting only those you want to kill your script through.
This is actually why set_error_handler() doesn't pair well with exceptions and set_exception_handler() when converting all errors to exceptions... unless you actually mean your application to be so strictly coded that any notice or warning halts the script. But at least it gives you a trace on that call involving an unset array key.
With a custom exception handler, you'll want to catch the exception in a try/catch block and do whatever handling you want in there.
The following is the example from The CodeUnit of Craig
try {
$error = 'Throw this error';
throw new Exception($error);
echo 'Never get here';
}
catch (Exception $e)
{
echo 'Exception caught: ', $e->getMessage(), "\n";
}
If you want to catch and print any unhandled exception, you can set a top level exception handler like this example from w3schools(near the bottom of the page)
<?php
function myException($exception){
echo "<b>Exception:</b> " , $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('Uncaught Exception occurred');
?>
should print: "Exception: Uncaught Exception occurred"
Look at the following code. it worked for me:
define(BR, "<br/>");
try {
echo "throwing exception" . BR;
throw new Exception("This is exception");
}
catch(Exception $ex) {
echo "caught exception: " . BR . $ex->getMessage() . BR;
}
echo "Keep on going!. ..." . BR;
it prints the following:
throwing exception
caught exception:
This is exception
Keep on going!. ...
What do you say ?
Can you show the code of your code handler ?
You could do this :
function handleError($errno, $errstring, $errfile, $errline, $errcontext) {
if (error_reporting() & $errno) {
// only process when included in error_reporting
return processError($errno, $errstring);
}
return true;
}
function handleException($exception){
// Here, you do whatever you want with the generated
// exceptions. You can store them in a file or database,
// output them in a debug section of your page or do
// pretty much anything else with it, as if it's a
// normal variable
}
function processError($code, $message){
switch ($code) {
case E_ERROR:
case E_CORE_ERROR:
case E_USER_ERROR:
// Throw exception and stop execution of script
throw new Exception($message, $code);
default:
// Execute exception handler and continue execution afterwards
return handleException(new Exception($message, $code));
}
}
// Set error handler to your custom handler
set_error_handler('handleError');
// Set exception handler to your custom handler
set_exception_handler('handleException');
// ---------------------------------- //
// Generate warning
processError(E_USER_WARNING, 'This went wrong, but we can continue');
// Generate fatal error :
processError(E_USER_ERROR, 'This went horrible wrong');
Alternate approach :
function handleError($errno, $errstring, $errfile, $errline, $errcontext) {
if (error_reporting() & $errno) {
// only process when included in error_reporting
return handleException(new \Exception($errstring, $errno));
}
return true;
}
function handleException($exception){
// Here, you do whatever you want with the generated
// exceptions. You can store them in a file or database,
// output them in a debug section of your page or do
// pretty much anything else with it, as if it's a
// normal variable
switch ($code) {
case E_ERROR:
case E_CORE_ERROR:
case E_USER_ERROR:
// Make sure script exits here
exit(1);
default:
// Let script continue
return true;
}
}
// Set error handler to your custom handler
set_error_handler('handleError');
// Set exception handler to your custom handler
set_exception_handler('handleException');
// ---------------------------------- //
// Generate warning
trigger_error('This went wrong, but we can continue', E_USER_WARNING);
// Generate fatal error :
trigger_error('This went horrible wrong', E_USER_ERROR);
An advantage of the latter strategy, is that you get the $errcontext parameter if you do $exception->getTrace() within the function handleException.
This is very useful for certain debugging purposes. Unfortunately, this works only if you use trigger_error directly from your context, which means you can't use a wrapper function/method to alias the trigger_error function (so you can't do something like function debug($code, $message) { return trigger_error($message, $code); } if you want the context data in your trace).
EDIT
I've found one dirty workaround for the trigger_error problem.
Consider the following code :
define("__DEBUG__", "Use of undefined constant DEBUG - assumed 'DEBUG'");
public static function handleError($code, $message, $file, $line, $context = false) {
if ($message == __DEBUG__) {
return static::exception(new \Exception(__DEBUG__, E_USER_WARNING));
} else {
if (error_reporting() & $code) {
return static::exception(new \Exception($message, $code));
}
return true;
}
}
public static function handleException($e) {
global $debug;
$code = $e->getCode();
$trace = $e->getTrace();
if ($e->getMessage() == __DEBUG__) {
// DEBUG
array_push($debug, array(
'__TIME__' => microtime(),
'__CONTEXT__' => array(
'file' => $trace[0]['file'],
'line' => $trace[0]['line'],
'function' => $trace[1]['function'],
'class' => $trace[1]['class'],
'type' => $trace[1]['type'],
'args' => $trace[0]['args'][4]
)
));
} else {
// NORMAL ERROR HANDLING
}
return true;
}
With this code, you can use the statement DEBUG; to generate a list of all available variables and a stack trace for any specific context. This list is stored in the global variable $debug. You can add it to a log file, add it to a database or print it out.
This is a VERY, VERY dirty hack, though, so use it at your own discretion. However, it can make debugging a lot easier and allows you to create a clean UI for your debug code.