Exceptions

An Exception object is thrown when an error occurs. It can be caught in a try block, and handled in a catch block. More than one catch blocks may be used to catch various exception classes, and the first matching clause will be used. We can throw our own exceptions.

<!DOCTYPE html>
<html>
<head></head>
<body><?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    else return 1/$x;
}
try {
    echo inverse(4);
    echo inverse(0);  // exception thrown
    echo "This part is not executed.";
} catch (Exception $e) {
    echo '<br />*** Caught exception ***';
    echo "<br /> Message:". $e->getMessage();
    echo "<br /> Code:". $e->getCode();
    echo "<br /> File:". $e->getFile();
    echo "<br /> Line:". $e->getLine();
    echo "<br /> Previous:". $e->getPrevious();
    echo "<br /> Trace String:". $e->getTraceAsString();
}
echo '<br />This part is printed.';
?> </body>
</html>

0.25
*** Caught exception ***
Message:Division by zero.
Code:0
File:D:\xampp\htdocs\contents\processed\en\php\exceptions.php
Line:7
Previous:
Trace String:#0 D:\xampp\htdocs\contents\processed\en\php\exceptions.php(13): inverse(0) #1 {main}
This part is printed.
The thrown object must be an instance of the Exception class or a subclass of Exception. The Exception class has the following members:

<?php
class Exception{
protected $message = 'Unknown exception'; 
private $string;
protected $code = 0;
protected $file;
protected $line;
private $trace;
private $previous; // previous exception if nested exception

public function __construct
     ($message = null, $code = 0, Exception $previous = null);
final private function __clone(); // no cloning of exceptions
final public function getMessage();
final public function getCode();
final public function getFile();
final public function getLine(); 
final public function getTrace(); // an array of the backtrace()
final public function getPrevious(); // previous exception
final public function getTraceAsString(); // formatted trace
public function __toString(); // formatted string for display
}
?>
Exceptions can be nested. An uncaught inner exception will be thrown to the outer try{…} catch(…) {…} block.

<!DOCTYPE html>
<html>
<head></head>
<body><?php
class E extends Exception{}
class F extends Exception{}
class G extends Exception{}
try{
   try {
      throw new E;
   } catch (F $exc){
      echo "Caught in the inner try block F.";
   } catch (G $exc){
      echo "Caught in the inner try block G.";
   }
} catch (E $exc){
   echo "Caught in the outer try block E.";
}
?> </body>
</html>

Caught in the outer try block E.
An uncaught exception causes a fatal error. Use set_exception_handler($f($e)) to handle any uncaught exceptions. set_exception_handler() takes in the exception $e, and returns the name of the previously defined exception handler. NULL is returned on error or if no exception handler was previously defined. If NULL is passed, resetting the handler to its default state, TRUE is returned.

<!DOCTYPE html>
<html>
<head></head>
<body><?php
function Exc_Handler($E){
   echo $E->getMessage();
}
set_exception_handler('Exc_Handler');
throw new Exception('Testing the exception handler...');
?> </body>
</html>

Testing the exception handler...
Since PHP 7.0, internal engine errors (like TypeError and DivisionByZeroError) are thrown as Error objects rather than causing old-style fatal errors, and both the Error hierarchy and the Exception hierarchy implement a common Throwable interface. Catching \Throwable lets a single catch block handle either kind uniformly:

<?php
function requireInt(int $x): int {
  return $x * 2;
}

function demo($value) {
  try {
    return requireInt($value);
  } catch (\Throwable $e) {
    return get_class($e) . ": " . $e->getMessage();
  }
}

echo demo(5) . "\n";
echo demo("not a number") . "\n";

class OutOfCandyException extends Exception {}

function checkStock(int $count) {
  if ($count <= 0) {
    throw new OutOfCandyException("No candy left!");
  }
  return "Candy dispensed";
}

try {
  echo checkStock(0) . "\n";
} catch (\Throwable $e) {
  echo get_class($e) . ": " . $e->getMessage() . "\n";
}
?>

10 TypeError: requireInt(): Argument #1 ($x) must be of type int, string given, called in D:\xampp\htdocs\throwable-interface.php on line 8 OutOfCandyException: No candy left!
Since PHP 7.1, a single catch block may list several exception/error types separated by |, catching any one of them without repeating the same handling code in separate blocks:

<?php
function parseLevel(int $level) {
  if ($level < 1 || $level > 10) {
    throw new ValueError("Level must be between 1 and 10.");
  }
  return "Level: $level";
}

function handle($input) {
  try {
    return parseLevel($input);
  } catch (TypeError|ValueError $e) {
    return "Rejected (" . get_class($e) . "): " . $e->getMessage();
  }
}

echo handle(5) . "\n";
echo handle(99) . "\n";
echo handle("abc") . "\n";
?>

Level: 5 Rejected (ValueError): Level must be between 1 and 10. Rejected (TypeError): parseLevel(): Argument #1 ($level) must be of type int, string given, called in D:\xampp\htdocs\multi-catch-union-types.php on line 11
Since PHP 8.0, catch no longer requires a variable to capture the caught object – when only the type matters and the exception's own details are not needed, the variable can be omitted entirely:

<?php
function safeDivide(int $a, int $b): ?int {
  try {
    return intdiv($a, $b);
  } catch (\DivisionByZeroError) {
    return null;
  }
}

var_dump(safeDivide(10, 2));
var_dump(safeDivide(10, 0));
?>

int(5) NULL
Since PHP 8.0, throw is an expression, not just a statement – it can appear anywhere an expression is allowed, such as on the right-hand side of the ?? null coalescing operator. This replaces an if block that used to be needed just to throw conditionally:

<?php
function getConfig(array $config, string $key) {
  return $config[$key] ?? throw new InvalidArgumentException("Missing config key: $key");
}

$config = ['debug' => true];

echo getConfig($config, 'debug') ? "true" : "false";
echo "\n";

try {
  getConfig($config, 'missing_key');
} catch (InvalidArgumentException $e) {
  echo "Caught: " . $e->getMessage() . "\n";
}
?>

true Caught: Missing config key: missing_key