I'm playing around with exceptions in PHP. For example, I have a script that reads a $_GET request and loads a file; If the file doesn't exists, an new exception should be thrown:
if ( file_exists( $_SERVER['DOCUMENT_ROOT'] .'/'.$_GET['image'] ) ) {
// Something real amazing happens here.
}
else {
throw new Exception("The requested file does not exists.");
}
The problem is that, when I try to supply an non existent file for the test, I got a 500 error instead of the exception message. The server log is the following:
[09-Jul-2013 18:26:16 UTC] PHP Fatal error: Uncaught exception 'Exception' with message 'The requested file does not exists.' in C:\sites\wonderfulproject\script.php:40
Stack trace:
#0 {main}
thrown in C:\sites\wonderfulproject\script.php on line 40
I wonder if I'm missing something real obvious here.
I've checked this question PHP fatal error: Uncaught exception 'Exception' with message but it's not quite like my issue, and have no concise answer.
Help, please?
* EDIT *
It seems this is something related to the throw keyword. If I use echo for example, I got the message printed on the screen, like this:
exception 'Exception' with message 'The file does not exists.' in C:\sites\wonderfulproject\script.php:183 Stack trace: #0 {main}
Why is that?
** EDIT 2 **
Thanks to #Orangepill, I got a better understanding about how to handle exceptions. And I found a superb tut from nettuts that helped a lot. The link: http://net.tutsplus.com/tutorials/php/the-ins-and-outs-of-php-exceptions/
This is expected behavior for an uncaught exception with display_errors off.
Your options here are to turn on display_errors via php or in the ini file or catch and output the exception.
ini_set("display_errors", 1);
or
try{
// code that may throw an exception
} catch(Exception $e){
echo $e->getMessage();
}
If you are throwing exceptions, the intention is that somewhere further down the line something will catch and deal with it. If not it is a server error (500).
Another option for you would be to use set_exception_handler to set a default error handler for your script.
function default_exception_handler(Exception $e){
// show something to the user letting them know we fell down
echo "<h2>Something Bad Happened</h2>";
echo "<p>We fill find the person responsible and have them shot</p>";
// do some logging for the exception and call the kill_programmer function.
}
set_exception_handler("default_exception_handler");
Just adding a bit of extra information here in case someone has the same issue as me.
I use namespaces in my code and I had a class with a function that throws an Exception.
However my try/catch code in another class file was completely ignored and the normal PHP error for an uncatched exception was thrown.
Turned out I forgot to add "use \Exception;" at the top, adding that solved the error.
For
throw new Exception('test exception');
I got 500 (but didn't see anything in the browser), until I put
php_flag display_errors on
in my .htaccess (just for a subfolder).
There are also more detailed settings,
see Enabling error display in php via htaccess only
Related
I don't know PHP. I have some PHP code written about 15 years ago by someone other than me. It has suddenly started throwing a fatal error
PHP Fatal error: Uncaught TypeError: Argument 1 passed to ReportException() must be an instance of Exception, instance of Error given
The stack trace shows a function ReportException() that takes an Exception:
function ReportException( Exception $e ) {
...
}
This function is called by another function ExceptionHandler() that takes an argument with no declared type, but which is presumed to be an Exception:
function ExceptionHandler( $e ) {
ReportException( $e );
...
}
The problem is, no other line in the code base calls ExceptionHandler(), so I can't trace where $e is being passed from to see why it's now an Error type instead of an Exception type.
There is this:
/**
* Install an exception handler.
*/
function InstallExceptionHandler() {
set_exception_handler( 'ExceptionHandler' );
}
which, when called (which it is), seems to set the ExceptionHandler() function as a general sort of Exception Handler. Not knowing PHP, though, I don't know how to follow this up further.
How can I determine why $e is coming to ExceptionHandler() as an Error instead of an Exception? I'm especially interested in answers that can suggest a testable theory about why this is suddenly an issue after the program has worked just fine for ~15 years. It's currently running on PHP 7.4.3, but I don't know what version it was written for.
Update
Barmar and Sammitch's suggestion to change the type of $e from Exception to Throwable causes the Fatal Error not to appear anymore. However, the app still does not work, so I can't say for certain that that's a full solution yet. I'll update when I know more.
Update 2
The app suddenly started working again, and with no fatal error. Ready to accept an answer.
I have set an exception handler in my PhP program using set_exception_handler() and it actually works fine. In the sense, it does catch exceptions not otherwise handled by me, and as provided in the handler, logs the exception details. So, why am I complaining? Problem is that in addition to logging the correct details with file name and line number in the exception handler, it also displays the following message in the browser:
Fatal error: Exception thrown without a stack frame in Unknown on line 0
My belief is that perhaps this specific exception message is coming from stdout stream while the exceptions been caught by the handler are from the stderr stream. The other possibility is that the above message is emitted by the error handler module and not the exception handler module of PhP. In any event, I would like all exception messages to go to one handler. I also have a error handler set as follows:
set_error_handler('SS_error_handler', E_ALL);
How are such situations handled? Is the Fatal error message coming from PhP's error message reporting module? If so, is there an overlap between the exception handler and the error handler in the sense that they both get triggered on certain errors/exceptions? If relevant, I would like to add that this specific exception is thrown be a MySQL PDO statement.
Any explanation would be appreciated.
Please reference the docs: http://php.net/manual/en/function.set-error-handler.php
The following error types cannot be handled with a user defined
function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING,
E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the
file where set_error_handler() is called.
Hence, you cannot use set_error_handler to catch exceptions, you should use proper try { } catch { } blocks.
add # character at the beginning of line that causes errors, that will silence it.
also you can ini_set('display_errors', 0), that will silence everyone :)
but usual people just try{} catch ( e) { trigger_error(e, E_USER_ERROR);}
I chose this title because I have the exact same problem as stated in here:
PHP exceptions thrown in error handler are not caught by exception handler
The author accepted the answer which said he obviously was doing something wrong.
My error and exception handler were working fine that last two years, but now im facing the exactly same problem.
I did a code update and also a server update (Plesk 11.5 running, the PHP version should be the same and is 5.3.2). I checked my code for the error, but a test made it clear that this cant be the problem:
I wrote the following testfile:
function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) {
throw new Exception("this was an error");
}
function exceptionHandler($e) {
echo 'exceptionHandler';
}
set_error_handler('errorHandler');
set_exception_handler('exceptionHandler');
// test one:
throw new Exception(); // outputs "exceptionHandler"
// test two - uncomment the first test of course!
$test->blabla();
The second test should also output "exceptionHandler", but it doesn't!
The output is "Fatal error: Call to a member function blabla() on a non-object in ......./exeptiontest.php on line 0"
This problem drives me crazy at the moment. Any suggestions here? Any PHP settings that cause this?
Update (After reading your comment).
After an error handler has been executed program flow would went back to the expression after that where the error occurred. But it is unreliable to pass back program flow to a fatally failed script. That's why error handlers won't get called on fatal errors. The documentation says:
The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.
As a workaround (depending on your needs), you may define a shutdown function using register_shutdown_function().
Original Answer (It turned out that this was not the problem here)
You need to read the documentation of set_exception_handler() carefully, especially the code example:
function exception_handler($exception) {
echo "Uncaught exception: " , $exception->getMessage(), "\n";
}
set_exception_handler('exception_handler');
throw new Exception('Uncaught Exception');
echo "Not Executed\n";
Meaning in your case that $test->blabla() will never gets executed.
You might expect that the exception handler function works like a catch block, but that isn't the case. True is, that if an exception occurs and no catch block is defined, the program flow will take over to the exception handler which may gracefully shutdown the script - but not more. If you want to handle exceptions the right way, use try / catch
Just to make it more clear: exception handlers behave different than error handlers. After returning from an exception handler the program will terminate while the program flow wents back to the expression after the error when returning from an error handler.
I'm attempting to post an open graph action to the Facebook Graph API but receiving an OAuth Exception (#3501) User is already associated to the <object>. That's all well and good, I expect Facebook to throw that exception. I get some other exceptions regarding authenticating a user (maybe with old/stale sessions, whatever).
My question is, has anyone else experienced that this exception is uncatchable in php? In this specific example (of posting graph actions) I am absolutely wrapping the call to the api in a try/catch statement; but I still get the fatal error.
<?php
try {
//publishing to open graph
$this->fb->api('/me/app:action', 'POST', array(
'object' => 'http://www.domain.com/path/to/graph/object',
));
}
catch (Exception $e)
{
/*
We may get here if the user has already posted this action before...
or if our session somehow went sour
or bc facebook is down...
or one of any other 1000 reasons the graph api is currently
sucking...
in any case it doesn't much matter, this is not a mission critical
thing to worry about; if we don't post the graph action - we don't
post the graph action..nbd.
*/
}
The above code is the snippet the publishes the graph action (generalized, because the content of it isn't important to this example).
I realize that the Exception that the Facebook PHP SDK is throwing is a FacebookApiException but that class extends Exception. I can't for the life of me figure out why in the name of all things logical, I can't catch my exception like this.
Has anyone experienced this issue? Is this a bug in the FB PHP SDK? Am I missing something else here? Thanks for your help!
Also, for reference, the relevant parts of the FB PHP SDK are here:
FacebookAPIException Definition (base_facebook.php line 30)
Throwing OAuthException (base_facebook.php line 1105
Edit 5/1/12
After some more investigation, it turns out that this "Exception" isn't really being treated like an exception at all. Typical Exceptions print out a stack trace back to the method call which resulted in throwing the exception. These "OAuthExceptions" do not. Also, typical exceptions pring out their error string a bit differently, for example:
PHP Fatal error: Uncaught exception 'Exception' with message 'foo' /path/to/file.php:10
or
PHP Fatal error: Uncaught exception 'MyException' with message 'stupid php' /path/to/file:10
#0 /path/to/file.php(17): doTest()
#1 {main}
thrown in /path/to/file.php on line 10
In this particular case, we don't get any of that, and it looks much more like a typical fatal error:
PHP Fatal error: Uncaught OAuthException: (#3501) User is already associated \
to the <object> object on a unique action type <action>. Original Action ID: \
123123123
thrown in /path/to/app/libs/fb/base_facebook.php on line 1107, \
referer: http://www.domain.com/path/to/page
I can't make any sense of why this forsaken "Exception" is so weird/uncatchable.
The Solution:
I figured out the answer to my own question; I've added it below - it's developer error, not a bug. The answer is below.
Also, this very well could be part of a bug, if you wanted to say that being able to reference a class definition as a type-hint to the catch definition which didn't exist (or wasn't available in the current namespace) is a bug.
So, something that's not outline above is that I'm utilizing PHP namespaces. This is a big gotchta since namespaces are relatively new to php, it's super easily overlooked I feel. Regardless, it's a pretty silly oversight/error.
If you're in a defined namespace (that is, not the root (\) namespace) you don't have direct access to the Exception class. Instead of php throwing a warning about not knowing what that class is, it just ignores the fact that it doesn't know what it is - and doesn't catch the exception.
Solution 1:
import the exception class:
<?php
use \Exception;
// ...codes
try {
//...codes
}
catch (Exception $e)
{
//...codes
}
Solution 2:
provide the full path to the exception class:
<?php
try {
//.....
}
catch (\Exception $e)
{
// voila.
}
I'm using throw new Exception(...) to handle errors, but these errors are huge! With 7 stack traces I get a 5 line error.
Let's say I call for a property that doesn't exist. I want to simply display the property X doesn't exist message, and the location where it was called: in file.php, line Y
Is that possible?
I assume you simply want this for your own personal debugging. You could do a few things:
a) Learn how to read the exception errors
b) Create an exception handler and only output a few things:
set_exception_handler(function(Exception $e)
{
echo $e->getMessage();
// echo out whatever you want to see
die();
});
Reference the docs to see what information is available.
c) Use an extension like xdebug that already provides a pretty exception handler
Use trigger_error and set_error_handler , and you'll be able to know LINE and FILE (in handler function).
Also, in handler you can call debug_backtrace and read all information that you need.