$30 off During Our Annual Pro Sale. View Details »

Exception handling - classic and fancy

Exception handling - classic and fancy

Exceptions are an integral part of PHP. PHP introduced them long ago, but handling has changed over the last versions. So the classic part contains a solid introduction to exception architecture, handling and how to use it. The fancy part will show some examples about modern exception logging.

Tommy Mühle

January 30, 2017
Tweet

More Decks by Tommy Mühle

Other Decks in Technology

Transcript

  1. Tommy Mühle | tommy-muehle.io Exception handling classic & fancy 1

  2. Tommy Mühle | tommy-muehle.io Tommy Mühle 
 Software Engineer Author

    2
  3. Tommy Mühle | tommy-muehle.io What is an Exception? 3

  4. Tommy Mühle | tommy-muehle.io Tommy Mühle | tommy-muehle.io 4 „An

    exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.“ https:/ /docs.oracle.com
  5. Tommy Mühle | tommy-muehle.io 5 http://php.net/manual/en/class.exception.php

  6. Tommy Mühle | tommy-muehle.io 6 http://php.net/manual/en/class.errorexception.php

  7. Tommy Mühle | tommy-muehle.io Catching 7

  8. Tommy Mühle | tommy-muehle.io 8 /* @var $connection \Doctrine\DBAL\Connection */

    $connection->beginTransaction(); try { // ... $connection->commit(); } catch (\Exception $exception) { $connection->rollBack(); throw $exception; }
  9. /* @var $connection \Doctrine\DBAL\Connection */ $connection->beginTransaction(); try { // ...

    $connection->commit(); } catch (Doctrine\DBAL\DBALException $exception) { $connection->rollBack(); } catch (\Exception $exception) { // ... throw $exception; } Tommy Mühle | tommy-muehle.io 9
  10. Tommy Mühle | tommy-muehle.io 10 /* @var $connection \Doctrine\DBAL\Connection */

    $connection->beginTransaction(); try { // ... $connection->commit(); } catch (\Exception $exception) { $connection->rollBack(); throw $exception; } finally { /* @var $logger \Monolog\Logger */ $logger->info('...'); }
  11. Tommy Mühle | tommy-muehle.io If you throw something, you have

    to catch it. 11
  12. Tommy Mühle | tommy-muehle.io Handling 12

  13. Tommy Mühle | tommy-muehle.io 13 function my_handler($exception) { echo 'Got

    it: ' . $exception->getMessage(); } set_exception_handler('my_handler'); throw new Exception('Take this!');
  14. Tommy Mühle | tommy-muehle.io PHP version specifications 14

  15. Tommy Mühle | tommy-muehle.io PHP 5 15

  16. Tommy Mühle | tommy-muehle.io PHP 5 16

  17. Tommy Mühle | tommy-muehle.io It’s dead, Jim. 17

  18. Tommy Mühle | tommy-muehle.io Exception hierarchy 18

  19. Tommy Mühle | tommy-muehle.io 19 http://php.net/manual/en/spl.exceptions.php

  20. Tommy Mühle | tommy-muehle.io Error as exception 20

  21. Tommy Mühle | tommy-muehle.io 21 function exception_error_handler ($severity, $message, $file,

    $line) { throw new ErrorException ($message, 0, $severity, $file, $line); } set_error_handler('exception_error_handler'); strpos(); // Trigger exception
  22. Tommy Mühle | tommy-muehle.io PHP 7 22

  23. Tommy Mühle | tommy-muehle.io PHP 7 22

  24. Tommy Mühle | tommy-muehle.io NEW Advanced exception hierarchy 23

  25. Tommy Mühle | tommy-muehle.io 24 http://php.net/manual/en/language.errors.php7.php

  26. Tommy Mühle | tommy-muehle.io 25 http://php.net/manual/en/class.throwable.php

  27. Tommy Mühle | tommy-muehle.io 26 http://php.net/manual/en/class.error.php

  28. Tommy Mühle | tommy-muehle.io 27 try { // ... }

    catch (Error $error) { // ... } catch (Exception $exception) { // ... }
  29. Tommy Mühle | tommy-muehle.io PHP 7.1 28

  30. Tommy Mühle | tommy-muehle.io Catching Multiple Exception Types 29

  31. try { // ... } catch (LengthException | OutOfRangeException $exception)

    { // ... } catch (Exception $exception) { // ... } Tommy Mühle | tommy-muehle.io 30
  32. Tommy Mühle | tommy-muehle.io Throw Error in Extensions 31

  33. Tommy Mühle | tommy-muehle.io 32 try { $myDateTime = unserialize('O:8:"DateTime":...";}');

    // ... } catch (Error $error) { // ... }
  34. Tommy Mühle | tommy-muehle.io Best practices 33

  35. Tommy Mühle | tommy-muehle.io Build custom exceptions upon SPL ones.

    34
  36. class FileNotFoundException extends InvalidArgumentException { } class FileNotReadableException extends RuntimeException

    { } Tommy Mühle | tommy-muehle.io 35 Build upon SPL exceptions
  37. Tommy Mühle | tommy-muehle.io Differentiate between logical and runtime exceptions.

    36
  38. Tommy Mühle | tommy-muehle.io Help developers with creating logical exceptions.

    37
  39. Tommy Mühle | tommy-muehle.io Create unavoidable
 runtime exceptions 
 if

    necessary. 38
  40. Tommy Mühle | tommy-muehle.io Create fully qualified 
 named exceptions.

    39
  41. Tommy Mühle | tommy-muehle.io 40 class NotFoundException extends Exception {

    // ... } Avoid unconcrete names
  42. class FileNotReadableException extends RuntimeException { } Tommy Mühle | tommy-muehle.io

    41 Use fully qualified names
  43. Tommy Mühle | tommy-muehle.io Add codes for 
 your exceptions.

    42
  44. Tommy Mühle | tommy-muehle.io 43 class FileNotReadableException extends RuntimeException {

    public function __construct(string $filename) { $message = sprintf('Cannot read %s!', $filename); $code = 666; parent::__construct($message, $code, null); } } Use specific codes
  45. Tommy Mühle | tommy-muehle.io Use named constructors for specific use

    cases. 44
  46. Tommy Mühle | tommy-muehle.io 45 $url = 'unreachable.tld'; if (''

    === $url) { throw new InvalidUrlException('Blank url are invalid!'); } if ('' === parse_url($url, PHP_URL_SCHEME)) { $message = sprintf('The url %s has no scheme!', $url); throw new InvalidUrlException($message); } // ... Avoid inline message generation
  47. Tommy Mühle | tommy-muehle.io 46 class InvalidUrlException extends InvalidArgumentException {

    private static function create(string $reason) { return new static($reason); } public static function blankUrl() { return static::create('Blank url are invalid!'); } } Use named constructors
  48. Tommy Mühle | tommy-muehle.io 47 class InvalidUrlException extends InvalidArgumentException {

    // ... public static function blankUrl() { return static::create('Blank url are invalid!'); } public static function noScheme(string $url) { $reason = sprintf('The url %s has no scheme!', $url); return static::create($reason); } // ... } One method for each case
  49. Tommy Mühle | tommy-muehle.io 48 $url = 'unreachable.tld'; if (''

    === $url) { throw InvalidUrlException::blankUrl(); } if ('' === parse_url($url, PHP_URL_SCHEME)) { throw InvalidUrlException::noScheme($url); } // ...
  50. Tommy Mühle | tommy-muehle.io Centralize own perseverative exceptions. 49

  51. Tommy Mühle | tommy-muehle.io Writing code to support PHP 5.x

    and 7 exceptions. 50
  52. Tommy Mühle | tommy-muehle.io 51 try { // Code that

    may throw an Exception or Error. } catch (Throwable $exception) { // Executed only in PHP 7, // will not match in PHP 5.x } catch (Exception $exception) { // Executed only in PHP 5.x, // will not be reached in PHP 7 }
  53. Tommy Mühle | tommy-muehle.io And now show 
 me some

    fancy stuff 52
  54. Tommy Mühle | tommy-muehle.io 53

  55. Tommy Mühle | tommy-muehle.io You send critical data to somebody

    else. 54
  56. Tommy Mühle | tommy-muehle.io 55 https://rollbar.com/demo/demo/

  57. Tommy Mühle | tommy-muehle.io 55 https://rollbar.com/demo/demo/ https://angel.co/bugsnag/jobs

  58. Tommy Mühle | tommy-muehle.io 55 https://rollbar.com/demo/demo/ https://angel.co/bugsnag/jobs https://www.g2crowd.com/products/raygun-crash-reporting/details

  59. Tommy Mühle | tommy-muehle.io 56

  60. Tommy Mühle | tommy-muehle.io Tommy Mühle | tommy-muehle.io 57 „Sentry

    is 100% open source. All features are built in the open and can be followed and contributed to on GitHub.“ https:/ /sentry.io/about
  61. Tommy Mühle | tommy-muehle.io 58 https://github.com/getsentry/sentry

  62. Tommy Mühle | tommy-muehle.io 59 https://hub.docker.com/_/sentry/

  63. Tommy Mühle | tommy-muehle.io Client usage 60

  64. Tommy Mühle | tommy-muehle.io 61 $sentryClient = new Raven_Client( 'https://<key>:<secret>@sentry.io/<project>'

    ); // or $sentryClient->install(); $error_handler = new Raven_ErrorHandler($sentryClient); $error_handler->registerExceptionHandler(); $error_handler->registerErrorHandler(); $error_handler->registerShutdownFunction();
  65. Tommy Mühle | tommy-muehle.io 62 $sentryClient->captureException($exception, [ 'extra' => [

    'php_version' => phpversion(), 'foo' => 'bar', // ... ], 'logger' => 'default', 'tags' => ['key' => 'value'], // group event by 'fingerprint' => ['{{ default }}', 'other value'], ]);
  66. Tommy Mühle | tommy-muehle.io 63

  67. Tommy Mühle | tommy-muehle.io 64

  68. Tommy Mühle | tommy-muehle.io 65

  69. Tommy Mühle | tommy-muehle.io 66

  70. Tommy Mühle | tommy-muehle.io 67

  71. Questions?

  72. Thank you! Slides http:/ /bit.ly/2kzZkjx Images https:/ /pixabay.com/ @tommy_muehle