Re: Re: RFC::Error Handling Guidelines for PHP5 packages

From: Date: Tue, 24 Aug 2004 10:10:36 +0000
Subject: Re: Re: RFC::Error Handling Guidelines for PHP5 packages
References: 1 2 3 4 5  Groups: php.pear.dev 
Request: Send a blank email to pear-dev+get-32869@lists.php.net to get a copy of this message
Davey wrote:
Sergio Carvalho wrote:
Greg Beaver wrote:
Hans L wrote:
I tend to agree that classes shouldn't have to implement their own subclasses if they don't want to; however, I recognize that catching package-specific errors is only possible if your package has its own exception subclass. How do you propose catching package specific errors? Maybe that's simply not essential, but it would certainly be useful.
It is essential. The only other way to do this is to have a member that defines the context or package (this is how PEAR_ErrorStack works). Without this information, it is very difficult to process the error in any way other than to simply log it or exit the program. Many error conditions need to be reported to different users in different ways. 1) different languages 2) different level of detail Without both package differentiation and error type, translating error messages is exceptionally difficult. How would you translate: "Error in fire.tpl template, missing parameter 3" if you don't know that the 3rd word will be the name of a template? Any generic translation would simply incorrectly translate fire into the native language. If you wish to provide less detail for mid-level users as in "There was an internal error in the fire.tpl template, please try again later" and more for admins (the more detailed template error example above), this is impossible without knowledge of how the error is structured. PEAR_ErrorStack, of course, recommends a separate array of parameters (like array('template' => 'fire.tpl')), but without knowledge of what the parameters mean, the information is useless. So, basically, package-specific errors is not only essential, anything that does not provide it will be no more advanced than trigger_error() with fancy wrapping paper.
Let me just add that, for Exceptions, the structuring can be a nudge more evolved than arrays of parameters. Exceptions are classes, and so can have any fields deemed necessary to describe the specific error they define. It's the same kind of information, defined in a more syntax-correct fashion. I like the idea of user-oriented and developer-oriented messages. Perhaps this can be integrated into PEAR_Exception. Maybe two different toString methods, or a toString method with a level parameter, defaulting to developer-oriented messages (so that an uncaught exception shows full debug info, but a caught exception can be used as the source for the user error message).
It is essential elements such as these concepts that are also missing from PEAR_Exception.
PEAR_Exception needs work, naturally. It's under development. I reinforce, however, that the specifics of PEAR_Exception are not essential for defining the coding guidelines. Discussion and contributions to PEAR_Exception are important in parallel or after the approval of coding guidelines.
Incidentally, PEAR_ErrorStack has been around for plenty of time to have read the documentation and to have both tried it out and discovered how to use it alongside exceptions with no pain in performance or disturbance to the natural use of exceptions. To claim it is "too recent" is well, just not true unless "too recent" really means "too much effort to actually take the 1 hour it takes to read the docs and start experimenting with it." That is something I can't do much about :).
I may have sounded too harsh (I tend to, in written form). I did read PEAR_ErrorStack code and docs, and played with it a bit (it took more than an hour ;-). I hope that this much has surfaced from my comments in the discussion leading to this RFC. I have, however, never used it in any of my packages, so I abstained from talking a lot about it (I don't like talking about subjects I'm not very secure about). My veredict on PEAR_ErrorStack is simple: It's an excellent class, but designed under the constraints of PHP4. We can get a cleaner design out for PHP5. PEAR_ErrorStack contains some features that duplicate stuff already present in the base PHP Exception (like error callbacks, or setting up error catchers), and other features that are more adapted to Warnings (like error levels). A clean separation of warning treatment vs error treatment is something I tried very hard to write into the RFC. I hope the energy currently going into this discussion pours into discussing warnings. Here, Greg, I think you'll add immense value by taking a lead role in forming the standard.
OK... let me try this one more time, if it fails I will blatantly disregard the RFC and only contribute PHP 4 packages in the future - if any, sorry. I'm going to bunch errors and warnings together, because quite frankly the user will be looking out for both of them. I have no problems with using Exceptions, they're good, they should be used. I also see that a lot of people will be mixing PHP4 and PHP5 PEAR classes or using PHP4 classes in PHP5. Why not have it so that whether you use PHP4 or PHP5 we can access the errors in the same way? When we seperate the warnings from the errors, in how they're reported to the user, we're going to create some UBER messy code. Imagine if you will: 1) PHP 4 package - uses PEAR_Error for errors and warning 2) PHP 4 package - uses PEAR_Error for errors and PEAR_ErrorStack for warnings 3) PHP 4 package - uses PEAR_ErrorStack for errors AND warnings 4) PHP 5 package - uses PEAR_Exception for errors and PEAR_ErrorStack for warnings (this is the only configuration allowed by your RFC) Now imagine you want to combine them all... we're going to have to include 3 different error systems in our code... UGLY. Now, imagine this: 1) PHP 4 package - uses PEAR_Error *internally* for errors and warnings, this means all PEAR_Errors are used for is for handling error conditions within the class. 2) PHP 4 package uses PEAR_Error and PEAR_ErrorStack *internally* for errors and warnings respectively (i.e. private stack) 3) PHP 4 package uses PEAR_ErrorStack for errors and warnings *internally* (again private stack) 4) PHP 5 package uses PEAR_Exception and PEAR_ErrorStack for errors and warnings (private stack) respectively *internally* (i.e. all exceptions are caught inside the class, and none will ever reach the user) 5) PHP 5 package uses PEAR_ErrorStack for errors and warnings (private stack) *internally* - a configuration not allowed by your RFC 6) Custom error handling - these ways are not the only ways and I'm sure some packages may require a custom solution. Now, all of these packages put these errors and warnings that can't be handled internally on a global error stack - this is the ONLY way the user will recieve errors - wow, how clean. This gives the package developer the free reign to do whatever they want for errors/warnings that are dealt with internally and will deliver the errors to the user via PEAR_ErrorStack The package user will then only have to deal with ONE way of catching and dealing with errors, warnings, notices, whatever. All packages can use this simple code: if (version_compare(PHP_VERSION, '5.0.0', '>=') === 1) {
    /* We're using PHP 5.0.0+ so lets use the E_STRICT compatible PEAR_ErrorStack */
    require_once 'PEAR/ErrorStack5.php';
} else {
    /* We're not using > PHP 5.0.0 so lets use the PHP 4 E_ALL compatible PEAR_ErrorStack */
    require_once 'PEAR/ErrorStack.php';
} This solution gives our developers the most freedom whilst delivering a unified (even when using PHP 4 and PHP 5 packages together) error reporting mechanism to our userbase. As I said, this is my final attempt to inject sanity into this... although I may contact the PEAR Group on this matter, only they can really interject now that the voting process has started. - Davey I think this whole thread could be addressed, by adding examples/code for integrating php4 code into php5. I don't see any movement going the other way, but I know in my framework at work thats the transition were doing right now, and will have php4 code running with php5 code for quite awhile.
In our case were just merging things at a global error handler, but in pear im guessing people will want to know howto throw a pear_error as an exception, and maybe even expect to see a helper method for doing this, Pear_exception_compat::createExceptionFromPearError or something similar. -josh

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