Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

    View full-size slide

  2. Tommy Mühle | tommy-muehle.io
    Tommy Mühle

    Software Engineer Author
    2

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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;
    }

    View full-size slide

  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

    View full-size slide

  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('...');
    }

    View full-size slide

  11. Tommy Mühle | tommy-muehle.io
    If you throw something,
    you have to catch it.
    11

    View full-size slide

  12. Tommy Mühle | tommy-muehle.io
    Handling
    12

    View full-size slide

  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!');

    View full-size slide

  14. Tommy Mühle | tommy-muehle.io
    PHP version
    specifications
    14

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  29. Tommy Mühle | tommy-muehle.io
    PHP 7.1
    28

    View full-size slide

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

    View full-size slide

  31. try {
    // ...
    } catch (LengthException | OutOfRangeException $exception) {
    // ...
    } catch (Exception $exception) {
    // ...
    }
    Tommy Mühle | tommy-muehle.io 30

    View full-size slide

  32. Tommy Mühle | tommy-muehle.io
    Throw Error
    in Extensions
    31

    View full-size slide

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

    View full-size slide

  34. Tommy Mühle | tommy-muehle.io
    Best practices
    33

    View full-size slide

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

    View full-size slide

  36. class FileNotFoundException
    extends InvalidArgumentException
    {
    }
    class FileNotReadableException
    extends RuntimeException
    {
    }
    Tommy Mühle | tommy-muehle.io 35
    Build upon SPL exceptions

    View full-size slide

  37. Tommy Mühle | tommy-muehle.io
    Differentiate between logical
    and runtime exceptions.
    36

    View full-size slide

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

    View full-size slide

  39. Tommy Mühle | tommy-muehle.io
    Create unavoidable

    runtime exceptions

    if necessary.
    38

    View full-size slide

  40. Tommy Mühle | tommy-muehle.io
    Create fully qualified

    named exceptions.
    39

    View full-size slide

  41. Tommy Mühle | tommy-muehle.io 40
    class NotFoundException extends Exception
    {
    // ...
    }
    Avoid unconcrete names

    View full-size slide

  42. class FileNotReadableException
    extends RuntimeException
    {
    }
    Tommy Mühle | tommy-muehle.io 41
    Use fully qualified names

    View full-size slide

  43. Tommy Mühle | tommy-muehle.io
    Add codes for 

    your exceptions.
    42

    View full-size slide

  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

    View full-size slide

  45. Tommy Mühle | tommy-muehle.io
    Use named constructors
    for specific use cases.
    44

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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);
    }
    // ...

    View full-size slide

  50. Tommy Mühle | tommy-muehle.io
    Centralize own
    perseverative exceptions.
    49

    View full-size slide

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

    View full-size slide

  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
    }

    View full-size slide

  53. Tommy Mühle | tommy-muehle.io
    And now show 

    me some fancy stuff
    52

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  61. Tommy Mühle | tommy-muehle.io 58
    https://github.com/getsentry/sentry

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  64. Tommy Mühle | tommy-muehle.io 61
    $sentryClient = new Raven_Client(
    'https://:@sentry.io/'
    );
    // or $sentryClient->install();
    $error_handler = new Raven_ErrorHandler($sentryClient);
    $error_handler->registerExceptionHandler();
    $error_handler->registerErrorHandler();
    $error_handler->registerShutdownFunction();

    View full-size slide

  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'],
    ]);

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide