An error is defined as an unexpected, invalid program state from which it is impossible to recover. For the sake of definition, recovery scope is defined as the method scope. Incomplete recovery is considered a recovery.
One pretty straightforward example for an error:
<?php
/**
* Connect to Specified Database
*
* @throws Example_Datasource_Exception When it can't connect
* to specified DSN.
*/
function connectDB($dsn)
{
$this->db =& DB::connect($dsn);
if (DB::isError($this->db)) {
throw new Example_Datasource_Exception(
"Unable to connect to $dsn:" . $this->db->getMessage()
);
}
}
?>
In this example the objective of the method is to connect to the given DSN. Since it can't do anything but ask PEAR DB to do it, whenever DB returns an error, the only option is to bail out and launch the exception.
The next example will introduce the concept of recovery:
<?php
/**
* Connect to one of the possible databases
*
* @throws Example_Datasource_Exception When it can't connect to
* any of the configured databases.
* @throws Example_Config_Exception When it can't find databases
* in the configuration.
*/
function connect(Config $conf)
{
$dsns =& $conf->searchPath(array('config', 'db'));
if ($dsns === false) {
throw new Example_Config_Exception(
'Unable to find config/db section in configuration.'
);
}
$dsns =& $dsns->toArray();
foreach ($dsns as $dsn) {
try {
$this->connectDB($dsn);
return;
} catch (Example_Datasource_Exception $e) {
// Some warning/logging code recording the failure
// to connect to one of the databases
}
}
throw new Example_Datasource_Exception(
'Unable to connect to any of the configured databases'
);
}
?>
This second example shows an exception being caught and recovered from. Altough the lower level connectDB method is unable to do anything but throw an error when one database connection fails, the upper level connect method knows the object can go by with any one of the configured databases. Since the error was recovered from, the exception is silenced at this level and not rethrown.
The last example illustrates incomplete recovery:
<?php
/**
* loadConfig parses the provided configuration. If the configuration
* is invalid, it will set the configuration to the default config.
*/
function loadConfig(Config $conf)
{
try {
$this->config = $conf->parse();
} catch (Config_Parse_Exception e) {
// Warn/Log code goes here
// Perform incomplete recovery
$this->config = $this->defaultConfig;
}
}
?>
The recovery produces side effects, so it is considered incomplete. However, the program may proceed, so the exception is considered handled, and must not be rethrown. As in the previous example, when silencing the exception, logging or warning should occur.