PHP 101 - PEAR error handling

ludo, Monday 18 August 2003 22:22:22

Read with interest today A Few Tips for Writing Useful Libraries in PHP (via PHP Everywhere), a nice article by the author of the MagpieRSS parser.

Posted a couple comments to the site, to which the author kindly replied by email. Nothing much, the usual "don't name your php files with an extension other than the one defined in your webserver", and an observation about error handling.

As all PHP developers know, PHP has no exceptions (and thus no try/something clauses), errors are either stored in special variables or accessed by calling functions, depending on what extension you're working with (PHP5 will introduce exceptions). All pretty messy, as the article author correctly points out.

One thing most developers don't know is that PEAR (the default PHP library bundled with the PHP source code) has a nice PEAR base class with great error handling features (why a good number of PHP developers stay away from PEAR is another matter entirely from the topic of this entry).

Basically, if your classes (you use PHP's OO features when writing reusable code, don't you?) inherit the PEAR base class, you get error handling for free (and a few other things, like destructors).

Using PEAR error handling is very easy, a quick example will suffice:

// our imaginary library (not very useful, is it?)

define('MYLIB_ERROR', 100);

require_once 'PEAR.php';

class myClass extends PEAR {

function myClass($myargs = null) { $this->PEAR(); }

function &raiseError($message, $method, $line) { $error = PEAR::raiseError(sprintf("%s.%s() line %d: %s", get_class($this), $method, $line, $message), MYLIB_ERROR); }

function myMethod() { $this->raiseError("hmmm something went wrong.....", 'myMethod', __LINE__); }

}

For our libray developer, that's all there is to it. Basically you import the base PEAR class, and use it as a base class for your library classes. Whenever you need to "throw" an exception, just raise a PEAR error. The raiseError method is what I use in my classes, makes much easier debugging what went wrong by appending the method name and the line number where the error occurred, and a constant I use to trap errors depending on the originating classes.

Let's see the user part of PEAR's error handling routines:

// user code accessing our library

PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'errorHandler'); function errorHandler($err) { echo("<b>PEAR error</b><br>message: <i>" . $err->getMessage() . "</i><br>user info: <i>" . $err->getUserInfo() . "</i><br>"); }

// or use any of the standard PEAR error messages, eg // PEAR::setErrorHandling(PEAR_ERROR_PRINT); // for development or a more sophisticated handler for production, // eg mailing a copy of the error or saving it in a log

$myinst =& new myClass(); $res = $myinst->myMethod(); if (PEAR::isError($res)) { // do something, the error is handled // (in our case printed) by the handler routine } else { // do something else }

The user only needs to import the PEAR base class (or alternatively use $myinst->isError() since it extends PEAR) and check method return values for possible errors. An added benefit of using PEAR's error handling routines is that by changing the function used to handle errors you can switch from debugging (ie print verbose error messages) to production (ie don't let the user see errors, handle them in your application) just by changing the error handling routine. A common practice is to automate this sort of things by checking the environment of the running server (eg hostname, etc.).

Readers' Comments

No user comments.