Les exceptions

Sommaire

PHP a une gestion des exceptions similaire à ce qu'offrent les autres langages de programmation. Une exception peut être lancée ("throw") et attrapée ("catch") dans PHP. Le code devra être entouré d'un bloc try pour faciliter la saisie d'une exception potentielle. Chaque try doit avoir au moins un bloc catch ou finally correspondant.

Si une exception est lancée et que la portée courante de la fonction n'a pas de block catch, l'exception "remontera" la pile d'appel de la fonction appelante jusqu'à trouver un bloc catch correspondant. Tous les blocs finally rencontrés seront exécutés. Si la pile d'appel est déroulée jusqu'à la portée globale sans rencontrer de bloc catch correspondant, le programme sera terminé avec une erreur fatale sauf si un gestionnaire global d'exception a été défini.

L'objet lancé doit être une instance de la classe Exception ou d'une sous-classe de la classe Exception. Tenter de lancer un objet qui ne correspond pas à cela résultera en une erreur fatale émise par PHP.

À partir de PHP 8.0.0, le mot clé throw est une expression et peut être utilisé dans n'importe quel contexte d'expressions. Dans les versions antérieures c'était une déclaration qui devait être sur sa propre ligne.

catch

Un bloc catch définit comment réagir à une exception qui a été lancée. Un bloc catch définit un ou plusieurs types d'exceptions ou erreurs qu'il peut gérer, et optionnellement une variable dans laquelle assigner l'exception. (Cette variable était requise dans les versions antérieures à PHP 8.0.0) Le premier bloc catch qu'une exception ou erreur lancée rencontre et qui correspond au type de l'objet lancé gérera l'objet.

Plusieurs blocs catch peuvent être utilisés pour attraper différentes classes d'exceptions. L'exécution normale (lorsqu'aucune exception n'est lancée dans le bloc try) continue après le dernier bloc catch défini dans la séquence. Les exceptions peuvent être lancées (throw) ou relancées dans un bloc catch. Sinon, l'exécution continuera après le bloc catch qui a été déclenché.

Lorsqu'une exception est lancée, le code suivant le traitement ne sera pas exécuté et PHP tentera de trouver le premier bloc catch correspondant. Si une exception n'est pas attrapée, une erreur fatale issue de PHP sera envoyée avec un message "Uncaught Exception ..." indiquant que l'exception n'a pu être attrapée à moins qu'un gestionnaire d'exceptions ne soit défini avec la fonction set_exception_handler().

À partir de PHP 7.1, un block catch peut spécifier plusieurs exceptions à l'aide du caratère pipe (|). Ceci est utile lorsque différentes exceptions de hiérarchies de classes différentes sont traitées de la même manière.

À partir de PHP 8.0.0, le nom de variable pour l'exception attrapée est optionnel. Si non spécifié, le bloc catch sera toujours exécuté mais n'aura pas accès à l'objet lancé.

finally

Un bloc finally peut aussi être spécifié après des blocs catch. Le code à l'intérieur du bloc finally sera toujours exécuté après les blocs try et catch, indépendamment du fait qu'une exception a été lancée, avant de continuer l'exécution normale.

Une interaction notable est entre un bloc finally et une déclaration return. Si une déclaration return est rencontrée à l'intérieur des blocs try ou catch, le bloc finally sera quand même exécuté. De plus, la déclaration return est évaluée quand elle est rencontrée, mais le résultat sera retourné après que le bloc finally soit exécuté. Additionnellement, si le bloc finally contient aussi une déclaration return la valeur du bloc finally est retournée.

Global exception handler

Si une exception est autorisée à remonter jusqu'à la portée globale, elle peut être attrapée par un gestionnaire d'exceptions global si il a été défini. La fonction set_exception_handler() peut définir une fonction qui sera appelée à la place d'un block catch si aucun autre block n'est invoqué. L'effet est essentiellement identique à entourer le programme entier dans un block try-catch avec cette fonction en tant que catch.

Notes

Note:

Les fonctions internes de PHP utilisent principalement l' Error reporting, seules les extensions orientées objet utilisent les exceptions. Quoiqu'il en soit, des erreurs peuvent facilement être traduites en exceptions avec ErrorException. Cependant, cette technique ne fonctionne que pour les erreurs non fatales.

Exemple #3 Convertir l'error reporting en exceptions

<?php
function exceptions_error_handler($severity$message$filename$lineno) {
    throw new 
ErrorException($message0$severity$filename$lineno);
}

set_error_handler('exceptions_error_handler');
?>

Exemples

Exemple #4 Lancer une exception

<?php
function inverse($x) {
    if (!
$x) {
        throw new 
Exception('Division par zéro.');
    }
    return 
1/$x;
}

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

// Continue execution
echo "Bonjour le monde !\n";
?>

L'exemple ci-dessus va afficher :

0.2
Exception reçue : Division par zéro.
Bonjour le monde !

Exemple #5 Gestion de l'exception avec un bloc finally

<?php
function inverse($x) {
    if (!
$x) {
        throw new 
Exception('Division par zéro.');
    }
    return 
1/$x;
}

try {
    echo 
inverse(5) . "\n";
} catch (
Exception $e) {
    echo 
'Exception reçue : ',  $e->getMessage(), "\n";
} finally {
    echo 
"Première fin.\n";
}

try {
    echo 
inverse(0) . "\n";
} catch (
Exception $e) {
    echo 
'Exception reçue : ',  $e->getMessage(), "\n";
} finally {
    echo 
"Seconde fin.\n";
}

// On continue l'exécution
echo "Bonjour le monde !\n";
?>

L'exemple ci-dessus va afficher :

0.2
Première fin.
Exception reçue : Division par zéro.
Seconde fin.
Bonjour le monde !

Exemple #6 Interaction entre le bloc finally et return

<?php

function test() {
    try {
        throw new 
Exception('foo');
    } catch (
Exception $e) {
        return 
'catch';
    } finally {
        return 
'finally';
    }
}

echo 
test();
?>

L'exemple ci-dessus va afficher :

finally

Exemple #7 Héritage d'une exception

<?php

class MyException extends Exception { }

class 
Test {
    public function 
testing() {
        try {
            try {
                throw new 
MyException('foo!');
            } catch (
MyException $e) {
                
// on la relance
                
throw $e;
            }
        } catch (
Exception $e) {
            
var_dump($e->getMessage());
        }
    }
}

$foo = new Test;
$foo->testing();

?>

L'exemple ci-dessus va afficher :

string(4) "foo!"

Exemple #8 Gestion des exceptions de capture multiple

<?php

class MyException extends Exception { }

class 
MyOtherException extends Exception { }

class 
Test {
    public function 
testing() {
        try {
            throw new 
MyException();
        } catch (
MyException MyOtherException $e) {
            
var_dump(get_class($e));
        }
    }
}

$foo = new Test;
$foo->testing();

?>

L'exemple ci-dessus va afficher :

string(11) "MyException"

Exemple #9 Omettre la variable attrapé

Seulement permis dans PHP 8.0.0 et ultérieur.

<?php

class SpecificException extends Exception {}

function 
test() {
    throw new 
SpecificException('Oopsie');
}

try {
    
test();
} catch (
SpecificException) {
    print 
"A SpecificException was thrown, but we don't care about the details.";
}
?>

Exemple #10 Throw en tant qu'expression

Seulement permis dans PHP 8.0.0 et ultérieur.

<?php

class SpecificException extends Exception {}

function 
test() {
    
do_something_risky() or throw new Exception('It did not work');
}

try {
    
test();
} catch (
Exception $e) {
    print 
$e->getMessage();
}
?>
add a note add a note

User Contributed Notes 32 notes

up
300
zmunoz at gmail dot com
13 years ago
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());
   }
  }

}
?>
up
99
ohcc at 163 dot com
7 years ago
If a TRY has a FINALLY, a RETURN either in the TRY or a CATCH won't terminate the script. Code in the same block after the RETURN will not be executed, and the RETURN itself will be "copied" to the bottom of the FINALLY block to be executed.

a RETURN in the FINALLY block will override value(s) returned from the TRY or a CATCH block.

An EXIT or a DIE always terminate the script after themselves.

code 1

<?php
   
function foo(){
       
$bar = 1;
        try{
            throw new
Exception('I am Wu Xiancheng.');
        }catch(
Exception $e){
            return
$bar;
           
$bar--; // this line will be ignored
       
}finally{
           
$bar++;
        }
    }
    echo
foo(); // 2
?>

code 2

<?php
   
function foo(){
       
$bar = 1;
        try{
            throw new
Exception('I am Wu Xiancheng.');
        }catch(
Exception $e){
            return
$bar;
           
$bar--; // this line will be ignored
       
}finally{
           
$bar++;
            return
$bar;
        }
    }
    echo
foo(); //2
?>

code 3

<?php
   
function foo(){
       
$bar = 1;
        try{
            throw new
Exception('I am Wu Xiancheng.');
        }catch(
Exception $e){
            return
$bar;
           
$bar--; // this line will be ignored
       
}finally{
            return
100;
        }
    }
    echo
foo(); //100
?>
up
6
shaman_master at list dot ru
4 years ago
Example for PHP 7.0 or latest:
<?php
namespace SomeNamespace;

use
Throwable, Exception, Error;

class
SomeClass
{
    public function
someMethod()
    {
        try {
            if (
rand(0, 1)) {
                throw new
Exception('Some message');
            } else {
                throw new
Error('Some message');
            }
        } catch (
Throwable $e) {
            \
var_dump($e->getMessage());
        }
    }
   
    public function
__toString()
    {
        try {
            return (string)
$this->someMethod();
        } finally {
            return
'';
        }
    }
}
?>
up
81
ask at nilpo dot com
14 years ago
If you intend on creating a lot of custom exceptions, you may find this code useful.  I've created an interface and an abstract exception class that ensures that all parts of the built-in Exception class are preserved in child classes.  It also properly pushes all information back to the parent constructor ensuring that nothing is lost.  This allows you to quickly create new exceptions on the fly.  It also overrides the default __toString method with a more thorough one.

<?php
interface IException
{
   
/* Protected methods inherited from Exception class */
   
public function getMessage();                 // Exception message
   
public function getCode();                    // User-defined Exception code
   
public function getFile();                    // Source filename
   
public function getLine();                    // Source line
   
public function getTrace();                   // An array of the backtrace()
   
public function getTraceAsString();           // Formated string of trace
   
    /* Overrideable methods inherited from Exception class */
   
public function __toString();                 // formated string for display
   
public function __construct($message = null, $code = 0);
}

abstract class
CustomException extends Exception implements IException
{
    protected
$message = 'Unknown exception';     // Exception message
   
private   $string;                            // Unknown
   
protected $code    = 0;                       // User-defined exception code
   
protected $file;                              // Source filename of exception
   
protected $line;                              // Source line of exception
   
private   $trace;                             // Unknown

   
public function __construct($message = null, $code = 0)
    {
        if (!
$message) {
            throw new
$this('Unknown '. get_class($this));
        }
       
parent::__construct($message, $code);
    }
   
    public function
__toString()
    {
        return
get_class($this) . " '{$this->message}' in {$this->file}({$this->line})\n"
                               
. "{$this->getTraceAsString()}";
    }
}
?>

Now you can create new exceptions in one line:

<?php
class TestException extends CustomException {}
?>

Here's a test that shows that all information is properly preserved throughout the backtrace.

<?php
function exceptionTest()
{
    try {
        throw new
TestException();
    }
    catch (
TestException $e) {
        echo
"Caught TestException ('{$e->getMessage()}')\n{$e}\n";
    }
    catch (
Exception $e) {
        echo
"Caught Exception ('{$e->getMessage()}')\n{$e}\n";
    }
}

echo
'<pre>' . exceptionTest() . '</pre>';
?>

Here's a sample output:

Caught TestException ('Unknown TestException')
TestException 'Unknown TestException' in C:\xampp\htdocs\CustomException\CustomException.php(31)
#0 C:\xampp\htdocs\CustomException\ExceptionTest.php(19): CustomException->__construct()
#1 C:\xampp\htdocs\CustomException\ExceptionTest.php(43): exceptionTest()
#2 {main}
up
2
David Spector
4 years ago
This page states, "Code may be surrounded in a try block, to facilitate the catching of potential exceptions." There are two ways in which code may be "surrounded". The obvious (intuitive) way is lexical enclosure: all the code to be protected by the try block is surrounded like this:

try
   {
   A();

   function A()
      {
      throw new Exception('error');
      echo "A()";
      } // A
   } // try
catch...

The other way to enclose is by execution (dynamic enclosure), like this:

try
   {
   A();
   } // try
catch...

function A()
   {
   throw new Exception('error');
   echo "A()";
   } // A

The sense in which code is "surrounded" for exception handling is dynamic (the second example above). This is because exception handling is dynamic and works by "unwinding" the execution stack.
up
9
christof+php[AT]insypro.com
6 years ago
In case your E_WARNING type of errors aren't catchable with try/catch you can change them to another type of error like this:

<?php
    set_error_handler
(function($errno, $errstr, $errfile, $errline){
            if(
$errno === E_WARNING){
               
// make it more serious than a warning so it can be caught
               
trigger_error($errstr, E_ERROR);
                return
true;
            } else {
               
// fallback to default php error handler
               
return false;
            }
    });

    try {
           
// code that might result in a E_WARNING
   
} catch(Exception $e){
           
// code to handle the E_WARNING (it's actually changed to E_ERROR at this point)
   
} finally {
           
restore_error_handler();
    }
?>
up
22
hweidmann at online dot de
8 years ago
catch doesn't check for the existence of the Exception class, so avoid typo.

<?php
  
class MyException extends Exception
  
{
      ...
   }

   try
   {
      throw new
MyException(...);
   }
   catch (
MuException $e) // <--- typo
  
{
      ...
   }
?>

You WON'T get
   Fatal error: Class MuException could not be loaded ...

You WILL get
   Fatal error: Uncaught exception 'MyException' ...
up
36
php at marcuspope dot com
10 years ago
Using a return statement inside a finally block will override any other return statement or thrown exception from the try block and all defined catch blocks.   Code execution in the parent stack will continue as if the exception was never thrown. 

Frankly this is a good design decision because it means I can optionally dismiss all thrown exceptions from 1 or more catch blocks in one place, without having to nest my whole try block inside an additional (and otherwise needless) try/catch block.

This is the same behavior as Java, whereas C# throws a compile time error when a return statement exists inside a finally block.  So I figured it was worth pointing out to PHP devs who may not have any exposure to finally blocks or how other languages do it.

<?php

function asdf()
{
    try {
        throw new
Exception('error');
    }
    catch(
Exception $e) {
        echo
"An error occurred";
        throw
$e;
    }
    finally {
               
//This overrides the exception as if it were never thrown
       
return "\nException erased";
    }
}

try {
    echo
asdf();
}
catch(
Exception $e) {
    echo
"\nResult: " . $e->getMessage();
}
?>

The output from above will look like this:

    An error occurred
    Exception erased

Without the return statement in the finally block it would look like this:

    An error occurred
    Result: error
up
67
Johan
12 years ago
Custom error handling on entire pages can avoid half rendered pages for the users:

<?php
ob_start
();
try {
   
/*contains all page logic
    and throws error if needed*/
   
...
} catch (
Exception $e) {
 
ob_end_clean();
 
displayErrorPage($e->getMessage());
}
?>
up
13
ohcc at 163 dot com
8 years ago
Type declarations will trigger Uncaught TypeError when a different type is passed. And it cannot be caught with the Exception class.
<?php
   
function xc(array $a){       
    }   
    try{
       
xc(4);
    }catch (
Exception $e){ // failed to catch it
       
echo $e->getMessage();
    }
?>

You should use TypeError instead for PHP 7+,

<?php
   
function xc(array $a){   
    }   
    try{
       
xc(4);
    }catch (
TypeError $e){
        echo
$e->getMessage();
    }
?>

In php version prior to 7.0, you should translate Catchable fatal errors to an exception and then catch it.

<?php
   
function exceptionErrorHandler($errNumber, $errStr, $errFile, $errLine ) {
        throw new
ErrorException($errStr, 0, $errNumber, $errFile, $errLine);
    }
   
set_error_handler('exceptionErrorHandler');
    function
s(array $a){       
    }
    try{
       
s(4);
    }catch (
Exception $e){
        echo
$e->getMessage();
    }
?>
up
5
mlaopane at gmail dot com
6 years ago
<?php

/**
* You can catch exceptions thrown in a deep level function
*/

function employee()
{
    throw new \
Exception("I am just an employee !");
}

function
manager()
{
   
employee();
}

function
boss()
{
    try {
       
manager();
    } catch (\
Exception $e) {
        echo
$e->getMessage();
    }
}

boss(); // output: "I am just an employee !"
up
20
jazfresh at hotmail.com
17 years ago
Sometimes you want a single catch() to catch multiple types of Exception. In a language like Python, you can specify multiple types in a catch(), but in PHP you can only specify one. This can be annoying when you want handle many different Exceptions with the same catch() block.

However, you can replicate the functionality somewhat, because catch(<classname> $var) will match the given <classname> *or any of it's sub-classes*.

For example:

<?php
class DisplayException extends Exception {};
class
FileException extends Exception {};
class
AccessControl extends FileException {}; // Sub-class of FileException
class IOError extends FileException {}; // Sub-class of FileException

try {
  if(!
is_readable($somefile))
     throw new
IOError("File is not readable!");
  if(!
user_has_access_to_file($someuser, $somefile))
     throw new
AccessControl("Permission denied!");
  if(!
display_file($somefile))
     throw new
DisplayException("Couldn't display file!");

} catch (
FileException $e) {
 
// This block will catch FileException, AccessControl or IOError exceptions, but not Exceptions or DisplayExceptions.
 
echo "File error: ".$e->getMessage();
  exit(
1);
}
?>

Corollary: If you want to catch *any* exception, no matter what the type, just use "catch(Exception $var)", because all exceptions are sub-classes of the built-in Exception.
up
4
jake at NOSPAM dot qzdesign dot co dot uk
6 years ago
Don't forget if your source file is in a namespace you will need to
<?php
use Throwable; // PHP 7
use Exception;
?>
or type the fully qualified class name (prefixed with `\`) as in
<?php
try {
 
// ...
} catch(\Throwable $e) {
 
// PHP 7
} catch(\Exception $e) {
 
// PHP 5
}
?>
otherwise you will only ever catch exceptions of the possibly non-existent classes `\YourNamespace\Throwable` and `\YourNamespace\Exception`!
up
13
jim at anderos dot com
10 years ago
If you are using a namespace, you must indicate the global namespace when using Exceptions.
<?php
namespace alpha;
function
foo(){
    throw new \
Exception("Something is wrong!");
   
// throw new Exception(""); will fail
}

try {
   
foo();
} catch( \
Exception $e ) {
   
// catch( Exception $e ) will give no warning, but will not catch Exception
   
echo "ERROR: $e";
}

?>
up
13
Shot (Piotr Szotkowski)
15 years ago
‘Normal execution (when no exception is thrown within the try block, *or when a catch matching the thrown exception’s class is not present*) will continue after that last catch block defined in sequence.’

‘If an exception is not caught, a PHP Fatal Error will be issued with an “Uncaught Exception …” message, unless a handler has been defined with set_exception_handler().’

These two sentences seem a bit contradicting about what happens ‘when a catch matching the thrown exception’s class is not present’ (and the second sentence is actually correct).
up
17
sander at rotorsolutions dot nl
10 years ago
Just an example why finally blocks are usefull (5.5)

<?php

//without catch
function example() {
  try {
   
//do something that throws an exeption
 
}
  finally {
   
//this code will be executed even when the exception is executed
 
}
}

function
example2() {
  try {
    
//open sql connection check user as example
    
if(condition) {
        return
false;
     }
  }
  finally {
   
//close the sql connection, this will be executed even if the return is called.
 
}
}

?>
up
8
Simo
9 years ago
#3 is not a good example. inverse("0a") would not be caught since (bool) "0a" returns true, yet 1/"0a" casts the string to integer zero and attempts to perform the calculation.
up
15
Edu
10 years ago
The "finally" block can change the exception that has been throw by the catch block.

<?php
try{
        try {
                throw new \
Exception("Hello");
        } catch(\
Exception $e) {
                echo
$e->getMessage()." catch in\n";
                throw
$e;
        } finally {
                echo
$e->getMessage()." finally \n";
                throw new \
Exception("Bye");
        }
} catch (\
Exception $e) {
        echo
$e->getMessage()." catch out\n";
}
?>

The output is:

Hello catch in
Hello finally
Bye catch out
up
7
telefoontoestel at nospam dot org
9 years ago
When using finally keep in mind that when a exit/die statement is used in the catch block it will NOT go through the finally block.

<?php
try {
    echo
"try block<br />";
    throw new
Exception("test");
} catch (
Exception $ex) {
    echo
"catch block<br />";
} finally {
    echo
"finally block<br />";
}

// try block
// catch block
// finally block
?>

<?php
try {
    echo
"try block<br />";
    throw new
Exception("test");
} catch (
Exception $ex) {
    echo
"catch block<br />";
    exit(
1);
} finally {
    echo
"finally block<br />";
}

// try block
// catch block
?>
up
7
cyrus+php at boadway dot ca
10 years ago
There's some inconsistent behaviour associated with PHP 5.5.3's finally and return statements. If a method returns a variable in a try block (e.g. return $foo;), and finally modifies that variable, the /modified/ value is returned. However, if the try block has a return that has to be evaluated in-line (e.g. return $foo+0;), finally's changes to $foo will /not/ affect the return value.

[code]
function returnVariable(){
    $foo = 1;
    try{
        return $foo;
    } finally {
        $foo++;
    }
}

function returnVariablePlusZero(){
    $foo = 1;
    try{
        return $foo + 0;
    } finally {
        $foo++;
    }
}

$test1 = returnVariable(); // returns 2, not the correct value of 1.
$test2 = returnVariablePlusZero(); // returns correct value of 1, but inconsistent with $test1.
[/code]

It looks like it's trying to be efficient by not allocating additional memory for the return value when it thinks it doesn't have to, but the spec is that finally is run after try is completed execution, and that includes the evaluation of the return expression.

One could argue (weakly) that the first method should be the correct result, but at least the two methods should be consistent.
up
4
Tom Polomsk
9 years ago
Contrary to the documentation it is possible in PHP 5.5 and higher use only try-finally blocks without any catch block.
up
1
wisetips at gmail dot com
5 years ago
You should put your whole program into a try/catch block. Doing so is considered a best practice, because it will allow the user to continue to work even when there are errors in the page!
up
9
michael dot ochs at gmx dot net
16 years ago
Actually it isn't possible to do:
<?php
someFunction
() OR throw new Exception();
?>

This leads to a T_THROW Syntax Error. If you want to use this kind of exceptions, you can do the following:

<?php
function throwException($message = null,$code = null) {
    throw new
Exception($message,$code);
}

someFunction() OR throwException();
?>
up
1
Mohammad Hossein Darvishanpour
8 years ago
<?php
function Test_Extention($var1)
{
    if(
$var1 == false)
    {
        throw new
Exception('Invalid !');
    }
}
//end function

try
{
   
Test_Extention(false);
   
printf("%s","Valid");
}

catch(
Exception $e)
{
   
printf("%s","Message : " . $e->getMessage());
}
?>
up
3
Sawsan
12 years ago
the following is an example of a re-thrown exception and the using of getPrevious function:

<?php

$name
= "Name";

//check if the name contains only letters, and does not contain the word name

try
   {
   try
     {
      if (
preg_match('/[^a-z]/i', $name))
       {
           throw new
Exception("$name contains character other than a-z A-Z");
       }  
       if(
strpos(strtolower($name), 'name') !== FALSE)
       {
          throw new
Exception("$name contains the word name");
       }
       echo
"The Name is valid";
     }
   catch(
Exception $e)
     {
     throw new
Exception("insert name again",0,$e);
     }
   }

catch (
Exception $e)
   {
   if (
$e->getPrevious())
   {
    echo
"The Previous Exception is: ".$e->getPrevious()->getMessage()."<br/>";
   }
   echo
"The Exception is: ".$e->getMessage()."<br/>";
   }

?>
up
3
jon at hackcraft dot net
17 years ago
Further to dexen at google dot me dot up with "use destructors to perform a cleanup in case of exception". The fact that PHP5 has destructors, exception handling, and predictable garbage collection (if there's a single reference in scope and the scope is left then the destructor is called immediately) allows for the use of the RAII idiom.

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization and my own http://www.hackcraft.net/RAII/ describe this.
up
0
daviddlowe dot flimm at gmail dot com
6 years ago
Starting in PHP 7, the classes Exception and Error both implement the Throwable interface. This means, if you want to catch both Error instances and Exception instances, you should catch Throwable objects, like this:

<?php

try {
    throw new
Error( "foobar" );
   
// or:
    // throw new Exception( "foobar" );
}
catch (
Throwable $e) {
   
var_export( $e );
}

?>
up
0
fjoggen at gmail dot com
17 years ago
This code will turn php errors into exceptions:

<?php
function exceptions_error_handler($severity, $message, $filename, $lineno) {
    throw new
ErrorException($message, 0, $severity, $filename, $lineno);
}

set_error_handler('exceptions_error_handler');
?>

However since <?php set_error_handler()?> doesn't work with fatal errors, you will not be able to throw them as Exceptions.
up
-3
sander at rotorsolutions dot nl
10 years ago
Just an example why finally blocks are usefull (5.5)

<?php

//without catch
function example() {
  try {
   
//do something that throws an exeption
 
}
  finally {
   
//this code will be executed even when the exception is executed
 
}
}

function
example2() {
  try {
    
//open sql connection check user as example
    
if(condition) {
        return
false;
     }
  }
  finally {
   
//close the sql connection, this will be executed even if the return is called.
 
}
}
up
-9
alex dowgailenko [at] g mail . com
12 years ago
If you use the set_error_handler() to throw exceptions of errors, you may encounter issues with __autoload() functionality saying that your class doesn't exist and that's it.

If you do this:

<?php

class MyException extends Exception
{
}

class
Tester
{
    public function
foobar()
    {
        try
        {
           
$this->helloWorld();
        } catch (
MyException $e) {
            throw new
Exception('Problem in foobar',0,$e);
        }
    }
   
    protected function
helloWorld()
    {
        throw new
MyException('Problem in helloWorld()');
    }
}

$tester = new Tester;
try
{
   
$tester->foobar();
} catch (
Exception $e) {
    echo
$e->getTraceAsString();
}
?>

The trace will only show $tester->foobar() and not the call made to $tester->helloWorld().

In other words, if you pass a previous exception to a new one, the previous exception's stack trace is taken into account in the new exception.
up
-9
Hayley Watson
9 years ago
Remember that Exceptions are also objects and can be handled as such; they can be constructed in and returned as values from functions, passed as arguments to other functions, and examined before being thrown. You don't have to throw it as soon as you have constructed it (the stack trace will of course reflect the moment the Exception was constructed, not the moment it was thrown).

You might, for example, want to collect additional information to include in YourException but you don't want to clutter up the YourException class or the code containing the "throw" statement by collecting the information there. Or you might want to do something (such as logging) with each Exception that is thrown from a certain region (catch it, pass it to the logging function, then rethrow it).
up
-8
jenshausdorf at gmail dot com
6 years ago
Please don't do something like this:

<?php
try {
   
// experimental stuff to check whether something works
} catch(\Throwable $e) {
    return
false;
} finally {
    return
true;
}
?>

Well, it is allowed syntax, it is bad practice, because once it hits the exception block, finally won't be called(because it exits the scope). Finally was invented to prevent duplicated code after one operation, regardless whether it was successful(for example closing the connection to a server). This way, you don't have any duplicated code. So you don't need to use this structure.
To Top