Book Image

Mastering PHP 7

By : Branko Ajzele
Book Image

Mastering PHP 7

By: Branko Ajzele

Overview of this book

PHP is a server-side scripting language that is widely used for web development. With this book, you will get a deep understanding of the advanced programming concepts in PHP and how to apply it practically The book starts by unveiling the new features of PHP 7 and walks you through several important standards set by PHP Framework Interop Group (PHP-FIG). You’ll see, in detail, the working of all magic methods, and the importance of effective PHP OOP concepts, which will enable you to write effective PHP code. You will find out how to implement design patterns and resolve dependencies to make your code base more elegant and readable. You will also build web services alongside microservices architecture, interact with databases, and work around third-party packages to enrich applications. This book delves into the details of PHP performance optimization. You will learn about serverless architecture and the reactive programming paradigm that found its way in the PHP ecosystem. The book also explores the best ways of testing your code, debugging, tracing, profiling, and deploying your PHP application. By the end of the book, you will be able to create readable, reliable, and robust applications in PHP to meet modern day requirements in the software industry.
Table of Contents (24 chapters)
Title Page
Credits
About the Author
About the Reviewers
www.PacktPub.com
Customer Feedback
Preface
16
Debugging, Tracing, and Profiling

Throwables


The exceptions in PHP are not a new concept. They have been around ever since PHP 5 was released. However, they did not encompass all of PHP's error handling because errors were not considered to be exceptions. PHP, at the time, had two-error handling systems. This made it tricky to deal with, as traditional errors were not catchable via the try...catch blocks exceptions. Certain tricks were possible, where one could have used the set_error_handler() function in order to set a user-defined error handler function, basically listening for errors and turning them into exceptions.

Let's look at the following example:

<?php

class Mailer
{
    private $transport;

    public function __construct(Transport $transport)
    {
        $this->transport = $transport;
    }
}

$transport = new stdClass();

try {
    $mailer = new Mailer($transport);
} catch (\Exception $e) {
    echo 'Caught!';
} finally {
    echo 'Cleanup!';
}

PHP 5 would not be able to catch this, and instead throws Catchable fatal error, as shown here:

Catchable fatal error: Argument 1 passed to Mailer::__construct() must be an instance of Transport, instance of stdClass given, called in /index.php on line 18 and defined in /index.php on line 6.

By adding the implementation of set_error_handler() before this code, as follows, we could turn that fatal error into an exception:

set_error_handler(function ($errno, $errstr) {
  throw new \Exception($errstr, $errno);
});

With the preceding code in place, the try...catch...finally blocks would now kick in as intended. However, there were error types that could not be caught with set_error_handler, such as E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler is called.

The PHP 7 release improved the overall error handling system by introducing the Throwable interface, and moving the errors and exceptions under its umbrella. It is now the base interface for any object that can be thrown via a throw statement. While we cannot extend it directly, we can extend the \Exception and \Error classes. While \Exception is the base class for all PHP and user exceptions, \Error is the base class for all internal PHP errors.

We could now easily rewrite our preceding try...catch...finally block into one of the following:

<?php

// Case 1
try {
    $mailer = new Mailer($transport);
} catch (\Throwable $e) {
    echo 'Caught!';
} finally {
    echo 'Cleanup!';
}

// Case 2
try {
    $mailer = new Mailer($transport);
} catch (\Error $e) {
    echo 'Caught!';
} finally {
    echo 'Cleanup!';
}

Notice the use of \Throwable in the first example catch block. Even though we cannot extend it, we can use it as a shorthand for catching both \Error and \Exception in a single catch statement.

Implementation of \Throwable brings a much needed alignment between errors and exceptions, making them easier to reason with.