ErrorException and set_exception_handler()
ErrorException and set_exception_handler()
am 11.12.2009 23:31:14 von Hannes Magnusson
Hello "randallgirard"
Since the bug tracker isn't really a discussion forum, lets move it to
the "General PHP User List" (which is a discussion forum).
Regarding bug#50446[1] you filed, either I am misunderstanding what
you are hoping to achieve or you are misunderstanding the expected
behavior/documentations.
As far as I can tell; you are expecting the "ErrorException" class to
be some sort of magical exception which turns normal E_USER_* errors
into exceptions, without actually behaving like exceptions (i.e.
stopping program execution if not caught).
If you have a "exception handler" registered (via
set_exception_handler()) and there is no try/catch block around the
code that triggered the exception (doesn't matter where the exception
is thrown, from set_error_handler() or regular code), then the
exception handler will kick in.
After the exception handler has done its job PHP will stop the
execution of the script. No matter what.
There are no exceptions to that. On uncaught exceptions (i.e. not
caught via catch() blocks) PHP *will* stop execution of the script.
There are multiple reasons for that, including:
* How should PHP know where to return to?
If an exception was thrown inside an method, which was called in a
function from global scope; Where do you expect PHP to continue from?
Global scope?
From the function that called the method?
From the method that threw the exception?
* Exceptions are thrown when there is something very very wrong.
If the application doesn't know how to handle that particular type of
exception (via a catch() block) then the application has no fallback
procedure in place. PHP has no other resort then to stop the execution
of the script.
* The ErrorException isn't treated specially from PHP point of view.
Its just another exception type, like InvalidArgumentException,
ErrorExeption, BadMethodCallException, LogicException,
RuntimeException, UnexpectedValueException.
There is no technical difference between the exceptions or any other
built-in exception classes.
The built-in exceptions (SPL has a good chunk) simply suggest a
standard naming convention for exceptions to use (to simplify the
catch() clauses in applications for example).
Those exceptions will be treated just as any other exceptions, so you
must catch them if you want to deal with them and continue the script
execution.
If you want to turn all your E_USER_* errors into exceptions then you
absolutely can.
If you prefer to throw an exception when something internally emits
E_* errors (for example, invalid parameters to functions) you can.
But you still have to catch() those exceptions.
The only reason why the ErrorException exists is because many people
in the past complained over the fact PHP didn't stop execution when
internal function emitted E_* errors (such as sending array to a
function that expects an string).
Now you can throw exceptions on such errors.
Simply create an error handler and make it throw Exception
(ErrorException maps nicely to the information contained in normal E_*
errors, as it contains the "error message", "the errors code"(E_*),
"severity" (fatal error/recoverable error/warning/notice/), the
filename it occurred, and line number.
Note: You still need to catch the exception if you want to continue
the program flow.
I don't quite understand your comment about E_USER_* errors being
useless. I use those error levels extensively when I can't to inform
the caller that something happened, but "I could still do the job the
caller expected".
I personally do not use exceptions for my application flow (*I*
consider it extremely bad practice). If I want to inform the
caller/developer that something I had to guess what he wanted, or if
something skeptical/wrong happend, I throw E_USER_* errors.
My main error handler is actually the set_error_handler(). My
"default" exception handler calls back to my error handler, as my
error handler allready deals with sever error conditions.
Hope it this post shed some light on ErrorException and set_exception_handler().
If not, please "reply-to-all" with your questions (I CCed
php-general@lists.php.net on this post, which is a discussion list).
-Hannes
[1] http://bugs.php.net/50446
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Re: ErrorException and set_exception_handler()
am 11.12.2009 23:57:41 von Hannes Magnusson
On Fri, Dec 11, 2009 at 23:39, Randall Girard w=
rote:
> Okay, my mistake.
>
>
> E_USER_WARNING and E_USER_NOTICE are supposed to continue execution,
> correct?
Correct.
> Then=A0 I will restate what I previously said. throwing ErrorException fr=
om an
No no. Stop there. Exceptions are *totally* different from E_*.
> ERROR_HANDLER(...) is useless iwht E_USER_WARNING and E_USER_NOTICE. Why?
> Because when you throw the exception from the ERROR_HANDLER, presumably i=
t
> may NOT get caught in a try/catch block. Therefor the execution cannot
> continue.
Exactly. And that is the point.
Why would you be turning E_USER_* into exceptions if you don't want to
bail out of the current scope?
If you throw an exception from the error handler, what exactly do you
expect to happen?
I gave several reasons for why that simply is impossible, but I am
curious: what exactly are you expecting?
> Therefor, I think that either a check to see if the TRY/CATCH has been
> initiated further up the call stack, or a function to call from within th=
e
> EXCEPTION_HANDLER that will return execution to the previous scope.
>
>
> I don't see how this is difficult to understand.
So you expect a scripting language to scroll up the entire execution
chain to see if there is a catch() block at all, and if there is no
catch() block, the simply ignore the exception and continue?
If thats your expectations then you are severely misunderstanding the
concept of exceptions.
Please do "reply-all". And please do not top-post.
-Hannes
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Re: Re: ErrorException and set_exception_handler()
am 14.12.2009 12:27:24 von Richard Quadling
2009/12/11 Hannes Magnusson :
> On Fri, Dec 11, 2009 at 23:39, Randall Girard =
wrote:
>> Okay, my mistake.
>>
>>
>> E_USER_WARNING and E_USER_NOTICE are supposed to continue execution,
>> correct?
>
> Correct.
>
>
>> Then I will restate what I previously said. throwing ErrorExceptio=
n from an
>
> No no. Stop there. Exceptions are *totally* different from E_*.
>
>
>> ERROR_HANDLER(...) is useless iwht E_USER_WARNING and E_USER_NOTICE. Why=
?
>> Because when you throw the exception from the ERROR_HANDLER, presumably =
it
>> may NOT get caught in a try/catch block. Therefor the execution cannot
>> continue.
>
> Exactly. And that is the point.
> Why would you be turning E_USER_* into exceptions if you don't want to
> bail out of the current scope?
>
> If you throw an exception from the error handler, what exactly do you
> expect to happen?
> I gave several reasons for why that simply is impossible, but I am
> curious: what exactly are you expecting?
>
>
>
>> Therefor, I think that either a check to see if the TRY/CATCH has been
>> initiated further up the call stack, or a function to call from within t=
he
>> EXCEPTION_HANDLER that will return execution to the previous scope.
>>
>>
>> I don't see how this is difficult to understand.
>
> So you expect a scripting language to scroll up the entire execution
> chain to see if there is a catch() block at all, and if there is no
> catch() block, the simply ignore the exception and continue?
> If thats your expectations then you are severely misunderstanding the
> concept of exceptions.
>
>
> Please do "reply-all". And please do not top-post.
>
>
> -Hannes
>
> --
> PHP General Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>
In support of Hannes, and hopefully providing a simpler script to show
what is happening.
-----------script------------
function uncaught_exception_handler(Exception $e) {
echo 'Exception : ', $e->getMessage(), PHP_EOL;
}
function uncaught_error_handler($i_ErrNo, $s_Error, $s_File, $i_Line,
$a_Context) {
echo 'A PHP error has been generated. It will be turned into an
exception.', PHP_EOL;
switch($i_ErrNo) {
case 0 : $s_ErrNo =3D '@'; return True; break;
case 1 : $s_ErrNo =3D 'E_ERROR'; break;
case 2 : $s_ErrNo =3D 'E_WARNING'; break;
case 4 : $s_ErrNo =3D 'E_PARSE'; break;
case 8 : $s_ErrNo =3D 'E_NOTICE'; break;
case 16 : $s_ErrNo =3D 'E_CORE_ERROR'; break;
case 32 : $s_ErrNo =3D 'E_CORE_WARNING'; break;
case 64 : $s_ErrNo =3D 'E_COMPILE_ERROR'; break;
case 128 : $s_ErrNo =3D 'E_COMPILE_WARNING'; break;
case 256 : $s_ErrNo =3D 'E_USER_ERROR'; break;
case 512 : $s_ErrNo =3D 'E_USER_NOTICE'; break;
case 1024 : $s_ErrNo =3D 'E_USER_NOTICE'; break;
case 2048 : $s_ErrNo =3D 'E_STRICT'; break;
case 4096 : $s_ErrNo =3D 'E_RECOVERABLE_ERROR'; break;
case 8192 : $s_ErrNo =3D 'E_DEPRECATED'; break;
case 16384 : $s_ErrNo =3D 'E_USER_DEPRECATED'; break;
}
throw new Exception("PHP Error : $s_Error ($s_ErrNo) in $s_File at
Line $i_Line", $i_ErrNo);
// Never reached as execution continues in the "catch" clause or by
a uncaught exception handler.
echo 'The exception has been thrown.', PHP_EOL;
}
set_error_handler('uncaught_error_handler');
set_exception_handler('uncaught_exception_handler');
try {
echo 'About to divide by zero inside a try/catch.', PHP_EOL;
$a =3D 1 / 0;
} catch(Exception $e) {
echo 'Caught : ', $e->getMessage(), PHP_EOL;
}
echo 'Caught divide by zero E_WARNING.', PHP_EOL, PHP_EOL;
echo 'About to divide by zero without a safety net.', PHP_EOL;
$b =3D 1 / 0;
// Never reached as we are not catching the execption thrown by the
uncaught error handler
echo 'Un-caught divide by zero E_WARNING.', PHP_EOL;
?>
-----------script------------
outputs ...
--------output---------
About to divide by zero inside a try/catch.
A PHP error has been generated. It will be turned into an exception.
Caught : PHP Error : Division by zero (E_WARNING) in Z:\test_error.php
at Line 36
Caught divide by zero E_WARNING.
About to divide by zero without a safety net.
A PHP error has been generated. It will be turned into an exception.
Exception : PHP Error : Division by zero (E_WARNING) in
Z:\test_error.php at Line 44
--------output---------
The whole issue is that you are using the (and I can't stress this
enough) _UNCAUGHT_ handlers.
These are the last ditch attempt / safety net for your code. It is
STILL your responsibility to pre-detect the potential errors and code
around them.
A try/catch block will be enough, as demonstrated - I successfully
capture a divide by zero.
Richard.
--=20
-----
Richard Quadling
"Standing on the shoulders of some very clever giants!"
EE : http://www.experts-exchange.com/M_248814.html
Zend Certified Engineer : http://zend.com/zce.php?c=3DZEND002498&r=3D213474=
731
ZOPA : http://uk.zopa.com/member/RQuadling
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Fwd: Re: ErrorException and set_exception_handler()
am 15.12.2009 12:32:51 von Richard Quadling
---------- Forwarded message ----------
From: Randall Girard
Date: 2009/12/14
Subject: RE: [PHP] Re: ErrorException and set_exception_handler()
To: rquadling@googlemail.com
I understood exactly what was going on in the code! (I'm no fool when
it comes to this) I just thought (logically) that if the ERROR_HANDLER
forces you to end the script when necessary, that the
EXCEPTION_HANDLER would have a similar function... Rather, there is
not a way at all to continue execution. Now that I contemplate this
further, I think I prefer this anyway as I would NOT want errors
firing for ANY reason on a production website! Additionally when one
error happens it often triggers a number of errors (if execution
continues) and when logging of course they are all logged. I would
rather have just the one backtraced error log, and so forth.
Thank you for your help however! It is much appreciated.
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php