Re: My Experience with PHP5 Error Handling (and possible

From: Date: Thu, 26 Aug 2004 01:09:25 +0000
Subject: Re: My Experience with PHP5 Error Handling (and possible
References: 1 2 3 4 5 6 7  Groups: php.pear.dev 
Request: Send a blank email to pear-dev+get-32950@lists.php.net to get a copy of this message
Greg Beaver wrote:
Alexey Borzov wrote:
Greg, sorry, but I understand "PEAR_ErrorStack geared towards exceptions" as "Let's make it easier to ignore errors, exceptions are bad as it's difficult to ignore them".
Put simply: your understanding is both false and annoying. I have stated repeatedly that I both use exceptions in my own php5 code, and that I agree with everything in the RFC. I have also stated that I didn't think the RFC goes far enough, and then even provided a way to ensure that the RFC doesn't lock us down into something premature through the idea of giving it a stability like packages. I have never said that I didn't want to use exceptions, only that we need more experience actually using them before we pin down how they *must* be used. I've also stated that Exceptions, although useful, do not solve absolutely every error-handling problem, and have posted these concerns in the wiki page. Somehow, none of them made it into the RFC. 1) handling multiple error conditions at once is very difficult with exceptions, and will need to be standardized 2) upgrading warnings to exceptions and downgrading exceptions to warnings is not difficult, but will be if it is not standardized. Your attack above is completely unfounded and has LITERALLY nothing to do with either what I've said or my code.
There is no "PEAR_Error-like abomination" here aside from inflammatory rhetoric that serves no useful or even useless purpose.
There *is*: adding cruft to the 'throw' will force people wanting to use PEAR packages use their idiosyncrasies of error handling. We'll have another incarnation of monstrous PEAR.php for which PEAR was bashed for quite some time, instead of getting rid of it completely.
If you can provide a single line of php that successfully backs up this claim, I will fall over backwards in surprise. First of all, end-users would not see any difference in exception handling if the package uses PEAR_ErrorStack as well. Why? PEAR_ErrorStack Does Not Replace Exceptions, And Never Was Intended To Do So (TM). How many friggin times must I say this people? End users will ONLY see exceptions bubbled up from throw(). Any potentially ignorable conditions will be on the error stack, and users will want to deal with them, but since they are on a stack, the error handling can happen separate from the logic - just like exceptions. The only potential difference inside a package would be if a developer wishes to throw an exception and also store it on the stack. Why would a developer want to do this? The only reasoning I can think of would be to take advantage of unified logging. As I have said in the past, I think that a unification of PEAR_Exception and PEAR_ErrorStack ideas would work nicely. Why can't both share the same log? PEAR_ErrorStack::push() returns an Exception object in php5, and a developer *may* choose to throw this object. Where the hell is the cruft? PEAR_ErrorStack can be used with older php4 packages to ease the transition to replacement packages for applications. My statement "PEAR_ErrorStack geared towards exceptions" was clearly defined in a previous mail that you conveniently ignored. I have defined it again for your convenience. Please don't ignore this one. Currently, here is how PEAR_ErrorStack works: in php4, push() returns an array, and error info is stored internally as an array. in php5, push() returns an exception, and error info is stored internally as an array. The advantage of this approach over storing an object, as I saw it, was that the error info was simply data, and didn't force any particular implementation of error stuff the way PEAR_Error does. My plan (which I have already said) was to re-tool PEAR_ErrorStack to be more friendly to warnings and in particular, to store error information
using Exception class names instead. This is because the class name can replace both the package and error code fields, simplifying the API substantially, and allowing easy promotion of a warning.
How will this work in PHP4? Also, I don't see how the class name can replace the error code unless you have a seperate exception class for every error. I have my exceptions setup like this: abstract Crtx_Exception {
    const CRTX_EXCEPTION_ERROR = 1;
    const CRTX_EXCEPTION_WARNING = 2;
    const CRTX_EXCEPTION_NOTICE = 3;
    public __construct($msg, $code) {
        parent::__construct($this->getMsg($msg), $code);
    }
    protected function getMsg($msg, $code) {
        // an array of messages like:
       $msg[self::CRTX_EXCEPTION_ERROR] = "Fatal Error: $msg";
       return $msg[$code];
    }
    // Added for use with my afforementioned Crtx_ErrorStack
    public function getLevel($code) {
        // an array of levels like:
        $level[self::CRTX_EXCEPTION_ERROR] = 'error';
        return $level[$code];
    }
} I then extend for each package, adding extra constants and overriding getMsg/getLevel as necessary (i.e. Crtx_SOAP_Exception or Crtx_XML_XSLT_Exception). The only way I can see to get the code, is $exception->getCode() - is this what you mean? Like I've tried to impress on certain people, If you're writing a PHP 5 only package you will do: class Some_Package5 { public function __construct() {
       if ($something_wrong) {
           throw new PEAR_Exception(...);
       }
} } If you're writing a PHP4 packagte, you will do: class Some_Package4 {
    function Some_Package() {
        if ($something_wrong) {
            return PEAR::raiseError(...);
            /*
             On PHP4 this will return a PEAR_Error, and place it on the ErrorStack
             On PHP5 this will return null, and place it on the stack (this is completely PHP4 compatible and won't require an eval('throw foo');
            */
        }
    }
} // if the user is creating PHP5 only code he can do: try {
    $obj = new Some_Package5;
    $obj2 = new Some_Package4;
} catch (PEAR_Exception $e) {
    // handle it
} // he can also do the below :) /* if the user is creating code for PHP5 that uses PHP4 packages (note you CANNOT use PHP5 classes in PHP4, thats not the point of my idea!) he will do: */ $obj = new Some_Package5; $obj2 = new Some_Package4; if (PEAR_ErrorStack::staticHasErrors('Some_Package5') || PEAR_ErrorStack::staticHasErros('Some_Package4')) {
    // handle it
} /* if the user is creating code for PHP4 only, he can't use Some_Package5 */ $obj = new Some_Package4; if (PEAR::isError($obj)) {
    // handle it
} OR if (PEAR_ErrorStack::staticHasErrors('Some_Package4')) {
    // handle it
} So you see, the user only needs to compromise exceptions when either: a) Working with PHP4 only b) using PHP4 packages in PHP5 If he is doing: c) using PHP5 packages in PHP4... it won't work or d) Using PHP5 packages in PHP5 only app, he will just use try...catch IF HE WANTS I hope this FINALLY explains things... - Davey

« previous php.pear.dev (#32950) next »