CHAPTER 4 ■ ADVANCED FEATURES
class ConfException extends Exception { }
The LibXmlError class is generated behind the scenes when SimpleXml encounters a broken XML
file. It has message and code properties, and resembles the Exception class. I take advantage of this
similarity and use the LibXmlError object in the XmlException class. The FileException and
ConfException classes do nothing more than subclass Exception. I can now use these classes in my code
and amend both __construct() and write():
// Conf class...
function __construct( $file ) {
$this->file = $file;
if (! file_exists( $file ) ) {
throw new FileException( "file '$file' does not exist" );
}
$this->xml = simplexml_load_file($file, null, LIBXML_NOERROR );
if (! is_object( $this->xml ) ) {
throw new XmlException( libxml_get_last_error() );
}
print gettype( $this->xml );
$matches = $this->xml->xpath("/conf");
if (! count( $matches ) ) {
throw new ConfException( "could not find root element: conf" );
}
}
function write() {
if (! is_writeable( $this->file ) ) {
throw new FileException("file '{$this->file}' is not writeable");
}
file_put_contents( $this->file, $this->xml->asXML() );
}
construct() throws either an XmlException, a FileException, or a ConfException, depending on
the kind of error it encounters. Note that I pass the option flag LIBXML_NOERROR to
simplexml_load_file(). This suppresses warnings, leaving me free to handle them with my XmlException
class after the fact. If I encounter a malformed XML file, I know that an error has occurred because
simplexml_load_file() won’t have returned an object. I can then access the error using
libxml_get_last_error().
The write() method throws a FileException if the $file property points to an unwriteable entity.
So, I have established that construct() might throw one of three possible exceptions. How can I
take advantage of this? Here’s some code that instantiates a Conf() object:
class Runner {
static function init() {
try {
$conf = new Conf( dirname(FILE)."/conf01.xml" );
print "user: ".$conf->get('user')."\n";
print "host: ".$conf->get('host')."\n";
$conf->set("pass", "newpass");
$conf->write();
} catch ( FileException $e ) {
// permissions issue or non-existent file
} catch ( XmlException $e ) {