Zend PHP 7 Certification – OOP – Exceptions

This post covers the Exceptions section of the OOP chapter when studying for the Zend PHP 7 Certification.

An exception can be thrown and caught within PHP like many other programming languages. In PHP, the throw keyword is used to throw an exception.

When wrapping code within a try block, the catch part of the block is used to facilitate the catching of potential exceptions.

Each try must have at least one corresponding catch or finally block.

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo "Hello World\n";

This would output the following.

0.2
Caught exception: Division by zero.
Hello World

So although an exception has been caught, execution continues as normal.

The thrown object must be an instance of the Exception class or a subclass of Exception. Trying to throw an object that is not will result in a fatal error.

In PHP 5.5 and later, a finally block may also be specified after or instead of catch blocks. Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}

try {
    echo inverse(5) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "First finally.\n";
}

try {
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "Second finally.\n";
}

// Continue execution
echo "Hello World\n";

Using a finally block would be useful if the user needs to clean resources such as closing a connection, or deleting temporary files.

When catching an exception inside a namespace it is important that you escape to the global space.

<?php
namespace SomeNamespace;

class SomeClass {

  function SomeFunction() {
      try {
          throw new Exception('Some Error Message');
      } catch (\Exception $e) {
          var_dump($e->getMessage());
      }
  }
}

This would output:

0.2
First finally.
Caught exception: Division by zero.
Second finally.
Hello World

In PHP 7, a TypeError can be thrown from mis-matched parameter or return types.

<?php
function add(int $num1, int $num2)
{
    return $num1 + $num2;
}

try {
    $value = add('num1', 'num2');
} catch (TypeError $e) {
    echo $e->getMessage(), "\n";
}

Outputs: Argument 1 passed to add() must be of the type integer, string given

Also in PHP 7, a Throwable interface is introduced. This is the base interface for any object that can be thrown via a throw statement, including the base Error and Exception classes.

The Exception class contains some useful methods that can be used when throwing an exception.

final public string getMessage ( void )
final public Exception getPrevious ( void )
final public mixed getCode ( void )
final public string getFile ( void )
final public int getLine ( void )
final public array getTrace ( void )
final public string getTraceAsString ( void )

Even though a Throwable interface exists in PHP 7, any custom exceptions classes created must extend the base Exception class.

<?php
class MyExceptionClass extends Exception
{
    public function __construct($message, $code = 0, Exception $previous = null) {
        // some code
    
        parent::__construct($message, $code, $previous);
    }

    public function __toString() {
        return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
    }

    public function customFunction() {
        echo "A custom function for this type of exception\n";
    }
}

View the other sections:

Note: This article is based on PHP version 7.0