elegant ways of handling php errors and exceptions
DESCRIPTION
Murphy was right: things will go wrong in any given situation if you only give them a chance. Therefore this session will discuss ways of limiting the risk of things going wrong in your application.TRANSCRIPT
![Page 1: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/1.jpg)
Copyright © 2008, Zend Technologies Inc.
ELEGANT WAYS OF HANDLING PHP ERRORS AND EXCEPTIONSBy Eddo Rotman
![Page 2: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/2.jpg)
Sep 17, 2008 | 2 |
Basically errors can be of one of two types• External Errors• Logic Errors (a.k.a. Bugs)
What about these error types?• External Errors will always occur at some point or another• External Errors which are not accounted for are Logic Errors• Logic Errors are harder to track down
Errors
![Page 3: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/3.jpg)
Sep 17, 2008 | 3 |
PHP Errors
Four levels of error severity to start with• Strict standard problems (E_STRICT)• Notices (E_NOTICE)• Warnings (E_WARNING)• Errors (E_ERROR)
![Page 4: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/4.jpg)
Sep 17, 2008 | 4 |
PHP Errors (cont)
// E_NOTICE$x = $y + 3;// E_WARNING$fh = fopen('thisisnotarealfile', 'r');// E_ERRORnonExistingFunction();
Notice: Undefined variable: y in /home/eddo/workspaces/neon/ZendCon08ServerIndie/xxx.php on line 6
Warning: fopen(thisisnotarealfile) [function.fopen]: failed to open stream: No such file or directory in /home/eddo/workspaces/neon/ZendCon08ServerIndie/xxx.php on line 8
Fatal error: Call to undefined function nonexistingfunction() in /home/eddo/workspaces/neon/ZendCon08ServerIndie/xxx.php on line 10
![Page 5: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/5.jpg)
Sep 17, 2008 | 5 |
User Triggered Errors
Almost the same as the ones in the previous slides• User triggered notice (E_USER_NOTICE)• User triggered warning (E_USER_WARNING)• User triggered error (E_USER_ERROR)
Triggering them is done using trigger_error()For example:
function getFooPlusOne($foo) {if (3 > $foo) {
trigger_error('foo has to be greater than 3', E_USER_ERROR);}return ($foo + 1);
}
![Page 6: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/6.jpg)
Sep 17, 2008 | 6 |
Additional Error TypesCatchable fatal error
• E_RECOVERABLE_ERROR – a probably dangerous error occurred. If not handled by the user, the application will abort as if this was an E_ERROR
Parsing errors
• E_PARSE – there is a syntactic error found while parsing the script. This is a fatal error
Compilation errors
• E_COMPILE_ERROR – a fatal error occurred in the engine while compiling the script
• E_COMPILE_WARNING - a nonfatal error occurred in the engine while compiling the script
PHP core errors
• E_CORE_ERROR – a fatal runtime error occurred in the engine
• E_CORE_WARNING – a nonfatal runtime error occurred in the engine
![Page 7: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/7.jpg)
Sep 17, 2008 | 7 |
Error Reporting Settings
Setting which errors PHP will report is done through the error_reporting directive
• in php.ini fileerror_reporting = E_ALL & ~E_NOTICE
• in runtimeerror_reporting(E_ALL & ~E_NOTICE);
• in .htaccess or apache.confphp_value error_reporting 6135
![Page 8: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/8.jpg)
Sep 17, 2008 | 8 |
Handling the Errors
There are four ways to handle errors
• Display them• Log them• Ignore them• Act on them
![Page 9: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/9.jpg)
Sep 17, 2008 | 9 |
Displaying Errors
How to display errors in the standard output -
• Set the display_errors directive to On
• Set the error_reporting to the appropriate severity level
Displaying errors is good for the programmer, bad for the user
![Page 10: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/10.jpg)
Sep 17, 2008 | 10 |
Displaying Errors (cont)
![Page 11: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/11.jpg)
Sep 17, 2008 | 11 |
Displaying Errors (cont)
![Page 12: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/12.jpg)
Sep 17, 2008 | 12 |
Logging Errors
How to set PHP to automatically log errors
• Set the log_errors directive to On
• Set the error_log directive to your preferred logging option
PHP supports two options for logging errors
• Logging to a file – set the error_log to a file path
• Logging to syslog – set the error_log to syslog
![Page 13: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/13.jpg)
Sep 17, 2008 | 13 |
Ignoring Errors
Don't do that.
![Page 14: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/14.jpg)
Sep 17, 2008 | 14 |
Acting on Errors
PHP enables us to set a default error handler using the set_error_handler() function
Five parameters will be passed to the user-defined error handler function
• integer $errno – error severity level• string $errstr – error message• string $errfile [optional] – filename where the error was raised• integer $errline [optional] – line number where the error was
raised• array $errcontext [optional] - an array of every variable that
existed in the scope the error was triggered in
![Page 15: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/15.jpg)
Sep 17, 2008 | 15 |
Acting on Errors (cont)
function demoErrorHandler($errno, $errstr, $errfile, $errline) {switch ($errno) {
case E_USER_ERROR:Logger::log(E_ERROR, $errstr, $errfile, $errline);require_once(FULL_PATH_DEFAULT_ERROR_PAGE);exit(1); // control the flowbreak;
case E_WARNING:case E_USER_WARNING:
Logger::log(E_WARNING, $errstr, $errfile, $errline);break;
case E_NOTICE:case E_USER_NOTICE:
Logger::log(E_NOTICE, $errstr, $errfile, $errline);break;
default:Logger::log(0, $errstr, $errfile, $errline);break;
}return true; // Avoid running PHP's internal error handler
}
set_error_handler("demoErrorHandler");
![Page 16: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/16.jpg)
Sep 17, 2008 | 16 |
Acting on Errors (cont)
What can the error handler do?
• Display a safer message to the user
• Insert the data into a DB
• Write to a file
• Send an email
• ...
Keep in mind that on nonfatal errors, your script will keep on running
![Page 17: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/17.jpg)
Sep 17, 2008 | 17 |
Handling External Errors
External errors will always occur at some point of an application's life-cycle
External errors which are not accounted for are bugsfor example:
• Assuming a DB connection always succeeds
• Assuming a file is opened properly
• Assuming an XML file has the right format
• ...
Assumption is the big mama of all....
![Page 18: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/18.jpg)
Sep 17, 2008 | 18 |
Handling External Errors (cont)
$fh = fopen($myfile, 'w');if ($fh) {
$fh>write('save the rhinos!');} else {
redirectToErrorPage('Failed opening an important file');die(1);
}
$fh = @fopen($myfile, 'w');$fh ->fwrite('save the rhinos!');
$db = mysql_connect();mysql_query('SELECT * FROM users WHERE id=18');
$db = mysql_connect();if (! $db) {
redirectToErrorPage('Could not connect to the database!');die(1);
}mysql_query('SELECT * FROM users WHERE id=18', $db);
![Page 19: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/19.jpg)
Sep 17, 2008 | 19 |
Zend Monitor
![Page 20: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/20.jpg)
Sep 17, 2008 | 20 |
Exceptions
An Exception can be thought of as a flow-control structure, or as an error control mechanism
• Exceptions should be used to handle logic errors• Exceptions may be considered as any other type of flow-
control syntax (such as if-else, while and foreach)• Exceptions are slower and consume more memory than other
flow-control syntaxes, therefore it is not recommended to use it as a flow-control structure per se
Unhandled Exceptions are fatal errors
![Page 21: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/21.jpg)
Sep 17, 2008 | 21 |
Exceptions (cont)
![Page 22: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/22.jpg)
Sep 17, 2008 | 22 |
Exceptions (cont)
Exceptions are classes and therefore you may extend them to fit your needs or serve as markers
class DataBaseException extends Exception {
}
class MathException extends Exception {
}
![Page 23: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/23.jpg)
Sep 17, 2008 | 23 |
Handling Exceptions
Terminology:• throw – the act of publishing an Exception• try block – a segment of the code which may have an
exception thrown in it• catch block – a segment of the code which handles an
exception if one happens• finally – is not available in PHP, but common in other
languages
![Page 24: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/24.jpg)
Sep 17, 2008 | 24 |
Handling Exceptions (cont)
try {
if (0 == $denominator) {throw new Exception('Zero denominator');
}
echo ($numerator / $denominator);
} catch (Exception $e) {
echo 'You can not divide by zero';die; // make sure the script stops
}
![Page 25: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/25.jpg)
Sep 17, 2008 | 25 |
Handling Errors (cont)
class Calculator {
/** * @param float $numerator * @param float $denominator * @return float * @throws MathException */function divide($numerator, $denominator) {
if (0 == $denominator) {throw new MathException('Zero denominator');
}
return ($numerator / $denominator);}
}
![Page 26: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/26.jpg)
Sep 17, 2008 | 26 |
Handling Exceptions (cont)
try {$calc = new Calculator();echo $calc>divide($numerator, $denominator);
} catch (MathException $e) {echo 'A mathematic integrity failure: ', $e>getMessage();
} catch (Exception $e) {echo 'A system error: ', $e>getMessage()
}echo 'Done';
It is possible to have several catch block for one try block where each is intended to catch a different type of Exception
![Page 27: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/27.jpg)
Sep 17, 2008 | 27 |
Exception Hierarchies
Since Exceptions are objects, i.e. instances of classes, you should take advantage of class hierarchy capabilities
e.g. have Db2Exception, MysqlException etc. extend DataBaseException
try {$user = new User($username);$user>authenticate($password);$user>getAccountBalance();
} catch (UserAuthenticationException $e) {echo "The user is not logged in";
} catch (DataBaseException $e) {Logger::logException('DB Error', $e);echo "The system has encounter some internal error";
} catch (Exception $e) {Logger::logException('Unknown error', $e);echo "The system has encounter some internal error";
}
![Page 28: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/28.jpg)
Sep 17, 2008 | 28 |
Advanced Exceptions
The basic Exception class is a written in C and most of its methods are defined as final
Since it is a PHP class it may be extended to fit your needs. You may add functions and attributes to it
You may only override its __toString() method
![Page 29: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/29.jpg)
Sep 17, 2008 | 29 |
Advanced Exceptions (cont)class MysqlException extends Exception {
private $comment = 'Zend Conference 2008 Example';private $backtrace;
public function __construct() {$this>code = mysql_errno(); $this>message = mysql_error();$this>backtrace = debug_backtrace();
}
public function __toString() {return 'Papa was a Rolling Stone';
}}
try {if (! mysql_connect()) {
throw new MysqlException();}
} catch (MysqlException $e) {echo $e->getMessage();
} catch (Exception $e) {// do something else
}
![Page 30: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/30.jpg)
Sep 17, 2008 | 30 |
Cascading Exceptions
Exceptions bubble up until they are caught in the first catch block which wraps them. As mentioned before, uncaught Exceptions are fatal errors
Use this behavior to cascade Exceptions, i.e. catch them in a smaller logic frame and bubble only the needed data up
![Page 31: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/31.jpg)
Sep 17, 2008 | 31 |
Cascading Exceptions (cont)
class User {public staticfunction fetch($username, $password) {
try {$sql = "SELECT username FROM users WHERE “;$sql.= “ (username={$username} AND password={$password}) “;$sql.= “ LIMIT 1";return (MysqlAdapter::fetch($sql));
} catch (DataBaseException $e) {Logger::logException('Db Error', $e);throw new UserExeption('Unable to authenticate the user');
}return false;
}}
try {$user = User::fetch('Eddo', 'karnaf');
} catch (Exception $e) {// redirect to an error pagedie;
}
![Page 32: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/32.jpg)
Sep 17, 2008 | 32 |
Constructors
PHP will always return an instance of the class when the constructor is called
Throwing an exception in a constructor will enable us to distinguish between a successful construction and a failure
If an Exception is called in a constructor, the destructor is not called
![Page 33: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/33.jpg)
Sep 17, 2008 | 33 |
Constructors (cont)
class User {
private $name;private $data;
public function __construct($name) {$this>name = (string)$name;$this>data = UserModel::getDataByName($name);
if (empty($this>data)) {throw new Exception("The system failed for {$name}");
}}
}
try {$user = new User('Eddo Rotman');
} catch (Exception $e) {throw new Exception('Could not find the user');
}
![Page 34: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/34.jpg)
Sep 17, 2008 | 34 |
Default Exception Handler
This is a user-defined top-level Exception Handler which will handle any uncaught Exception
Unlike a try-catch block, after handling an Exception with the default error handler, the script halts
Keep in mind that the default exception handler can not catch all uncaught exceptions which may happen in your code
![Page 35: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/35.jpg)
Sep 17, 2008 | 35 |
Default Exception Handler
function myDefaultExceptionHandler($exception) {// do something about it
}
set_exception_handler('myDefaultExceptionHandler');
class MyExcpetionHandling {
public static function doSomething($exception) {// do something about it
}}
set_exception_handler(array('MyExcpetionHandling', 'doSomething'));
![Page 36: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/36.jpg)
Sep 17, 2008 | 36 |
Conclusions
• Errors happen, but it doesn't mean they should be ignored
• Watch out for external errors or they may turn to bugs
• Use Exceptions to better handle errors and logic flaws
• Use Exceptions to distinguish between different error cases
• Have a default error handler and a default exception handler, even if you are sure that everything is covered
![Page 37: Elegant Ways of Handling PHP Errors and Exceptions](https://reader034.vdocument.in/reader034/viewer/2022052619/55529b40b4c905e8128b4f07/html5/thumbnails/37.jpg)
Sep 17, 2008 | 37 |
Questions?