Re: My Experience with PHP5 Error Handling (and possible solutions)
| From: | Justin Patrin | Date: | Tue, 24 Aug 2004 21:51:30 +0000 |
| Subject: | Re: My Experience with PHP5 Error Handling (and possible solutions) | ||
| References: | 1 | Groups: | php.pear.dev |
| Request: | Send a blank email to pear-dev+get-32921@lists.php.net to get a copy of this message | ||
On Tue, 24 Aug 2004 16:45:57 -0400, Davey <davey@php.net> wrote:
> Dear PEARs,
>
> please don't take my ranting and raving about error handling as me just
> being crazy, I want to tell you about my experiences with PHP 5 with
> regards to using PEAR packages meant for PHP 4 as well as wanting to use
> exceptions.
>
> I am (and have been for about 5 months) writing a development framework,
> and whilst doing so I have been keenly aware that most likely, it won't
> be just me using it - I've been using the PEAR packaging system, and the
> same category system, this means anybody who has used PEAR will know how
> to use my framework. However, because its PHP 5 code and I wanted to use
> all the new PHP 5 goodies, I started using exceptions for the framework
> code...
>
> The framework is called Cerebral Cortex, and I use a Crtx_ prefix to all
> packages and therefore class names.
>
> First of all, I had the bright idea of just throwing PEAR_Error's as
> exceptions... to do this, I needed to take the PEAR_Error information
> and create a new Crtx_Exception with it. *bzzt* didn't work well, it
> ended up with a mess of code just to re-package an error.
>
> Next, I thought about using PEAR_ErrorStack, but instead of using
> ErrorStack to output the exceptions, I wanted to catch the exceptions
> and add them to the stack (that way, I could do some recovery and maybe
> not need to add them to the stack). To this end, I wrote a wrapper
> around PEAR_ErrorStack which would take the exception and add it to the
> appropriate package stack.
>
> This however, doesn't really work too well, mostly because my code was
> broken and I didn't want to keep repeating:
>
> try {
>
> }
> catch (Crtx_Exception $e) {
> $stack = Crtx_ErrorStack::createStack($e->package);
> $stack->push($e);
> }
>
> Furthermore, PEAR_Errors are left out to dry...
>
> My latest attempt, which I am thinking through right now, is to write a
> handler for PEAR_Error which will throw them as exceptions, and a
> set_exception_handler() which will catch all *uncaught* exceptions and
> add them to the stack.
Of course, this means that your program is effectively dead as your
code has jumped out of *all* levels. If you try this:
<?php
function eh($ex) {
echo 'exception thrown
';
}
set_exception_handler('eh');
function te() {
throw new Exception('exception');
}
echo 'before throw
';
te();
echo 'after throw
';
?>
You don't get the "after throw". Internals could add an "at-throw"
exception handler, but this breaks the exception paradigm.
>
> This means that I can just forget about try...catch if I know I can't
> recover, or if its not fatal (yes, I use exceptions for any error where
> the flow needs to be interuptted).
>
> For warnings and notices, I just place those directly onto the stack.
>
> Furthermore, I have a special stack "user" which will have errors like
> "You need to fill in this form field" (i.e. user friendly notices for
> output to users) which the developer can choose to use, or to ignore.
>
> This is *the* best solution I can come up with, as it allows the user to
> just do their own set_exception_handler() to override it.
>
> I think if perhaps we come up with a solution that does the following,
> we can use exceptions in PHP5 and PEAR_ErrorStack in PHP4...
>
> We could do the following:
> 1) On PHP 4, it will use PEAR_Error with a callback to add it to the
> ErrorStack by default
> 2) On PHP 5, we can use set_exception_handler() to have a "callback"
> that places them on the ErrorStack by default
>
> We then do something like this:
>
> $error = PEAR_Error::raiseError(''); - This will on PHP5, throw an error
> (which, if not caught will be just added to the stack) and return null,
> on PHP4 it will return a PEAR_Error (which is also added to the stack)
> same as now...
>
> On PHP5 *only* packages, we can use PEAR_Exception, which will have the
> same effect... except it won't use PEAR_Error
>
> What do you people think? I think that if we have a slimmed down
> PEAR_ErrorStack (I'm thinking perhaps, make it entirely static, and not
> do anything with PEAR_Error/Exceptions) it will work great...
>
> This way, when mixing PHP5 and PHP4, you can just let things go and use
> the ErrorStack (which will work in scripts across PHP4 and PHP5), or you
> can use a combination of the current PEAR_Error stuff and try...catch,
> or a combination of PEAR_ErrorStack and try...catch or all three
> together (eugh).
>
> This is the best solution for PEAR that I can come up with.
>
> - Davey
>
As has been said many times before, any solution you come up with is
going to break something. If you dumb down the exceptions to work in
PHP4 as well, you're going to lose things like automatic bubble-up. It
makes much more sense to define a PHP5 only error handling method and
enforce it. During the transition, it may / will be klunky to work
with PHP4 and PHP5 packages together, but something similar to the
below code can convert all PEAR_Errors to PEAR_Exceptions:
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'throwInstead');
function throwInstead($err) {
//I may be using thos wrong and missing things, but you get the idea
throw new PEAR_Exception($err->getMessage());
}
True, this breaks internal error handling for PHP4 packages, but then
again, you really shouldn't be using PHP4 packages along-side PHP5
ones for too long. I know it takes a while to migrate (I have a huge
code-base I haven't even started on yet), but going with something
simple and elegant is much better than kludging it, then having to
change our error handling yet again down the road.
--
DB_DataObject_FormBuilder - The database at your fingertips
http://pear.php.net/package/DB_DataObject_FormBuilder
paperCrane --Justin Patrin--