CHAPTER 4 ■ ADVANCED FEATURES
}
$conf = $this->xml->conf;
$this->xml->addChild('item', $value)->addAttribute( 'name', $key );
}
}
The Conf class uses the SimpleXml extension to access name value pairs. Here’s the kind of format
with which it is designed to work:
<?xml version="1.0"?>
The Conf class’s constructor accepts a file path, which it passes to simplexml_load_file(). It stores
the resulting SimpleXmlElement object in a property called $xml. The get() method uses XPath to locate
an item element with the given name attribute, returning its value. set() either changes the value of an
existing item or creates a new one. Finally, the write() method saves the new configuration data back to
the file.
Like much example code, the Conf class is highly simplified. In particular, it has no strategy for
handling nonexistent or unwriteable configurations. It is also optimistic in outlook. It assumes that the
XML document will be well-formed and contain the expected elements.
Testing for these error conditions is relatively trivial, but I must still decide how to respond to them
should they arise. You generally have two options:
First, I could end execution. This is simple but drastic. My humble class would then takes
responsibility for bringing an entire script crashing down around it. Although methods like
__construct() and write() are well placed to detect errors, they do not have the information to decide
how to handle them.
Rather than handle the error in my class, then, I could return an error flag of some kind. This could
be a Boolean or an integer value such as 0 or -1. Some classes will also set an error string or flag so that
the client code can request more information after a failure.
Many PEAR packages combine these two approaches by returning an error object (an instance of
PEAR_Error), which acts both as notification that an error has occurred and contains the error message
within it. This approach is now deprecated, but plenty of classes have not been upgraded, not least
because client code often depends upon the old behavior.
The problem here is that you pollute your return value. PHP does not enforce a unified return value.
At the time of this writing, there is no support for return class type hinting in PHP, so there is nothing to
prevent you from returning an error flag instead of the promised object or primitive. When you do this,
you have to rely on the client coder to test for the return type every time your error-prone method is
called. This can be risky. Trust no one!
When you return an error value to the calling code, there is no guarantee that the client will be any
better equipped than your method to decide how to handle the error. If this is the case then the problem
begins all over again. The client method will have to determine how to respond to the error condition,
maybe even implementing a different error reporting strategy.
Exceptions
PHP 5 introduced exceptions to PHP, a radically different way of handling error conditions. Different for
PHP, that is. You will find them hauntingly familiar if you have Java or C++ experience. Exceptions
address all of the issues that I have raised so far in this section.