Movatterモバイル変換


[0]ホーム

URL:


    Extending Exceptions »
    « Errors in PHP 7

    Exceptions

    Table of Contents

    PHP has an exception model similar to that of other programming languages. An exception can bethrown, and caught ("catched") within PHP. Code may be surrounded in atry block, to facilitate the catching of potential exceptions. Eachtry must have at least one correspondingcatch orfinally block.

    If an exception is thrown and its current function scope has nocatch block, the exception will "bubble up" the call stack to the calling function until it finds a matchingcatch block. Allfinally blocks it encounters along the way will be executed. If the call stack is unwound all the way to the global scope without encountering a matchingcatch block, the program will terminate with a fatal error unless a global exception handler has been set.

    The thrown object must be aninstanceofThrowable. Trying to throw an object that is not will result in a PHP Fatal Error.

    As of PHP 8.0.0, thethrow keyword is an expression and may be used in any expression context. In prior versions it was a statement and was required to be on its own line.

    catch

    Acatch block defines how to respond to a thrown exception. Acatch block defines one or more types of exception or error it can handle, and optionally a variable to which to assign the exception. (The variable was required prior to PHP 8.0.0.) The firstcatch block a thrown exception or error encounters that matches the type of the thrown object will handle the object.

    Multiplecatch blocks can be used to catch different classes of exceptions. Normal execution (when no exception is thrown within thetry block) will continue after that lastcatch block defined in sequence. Exceptions can bethrown (or re-thrown) within acatch block. If not, execution will continue after thecatch block that was triggered.

    When an exception is thrown, code following the statement will not be executed, and PHP will attempt to find the first matchingcatch block. If an exception is not caught, a PHP Fatal Error will be issued with an "Uncaught Exception ..." message, unless a handler has been defined withset_exception_handler().

    As of PHP 7.1.0, acatch block may specify multiple exceptions using the pipe (|) character. This is useful for when different exceptions from different class hierarchies are handled the same.

    As of PHP 8.0.0, the variable name for a caught exception is optional. If not specified, thecatch block will still execute but will not have access to the thrown object.

    finally

    Afinally block may also be specified after or instead ofcatch blocks. Code within thefinally block will always be executed after thetry andcatch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.

    One notable interaction is between thefinally block and areturn statement. If areturn statement is encountered inside either thetry or thecatch blocks, thefinally block will still be executed. Moreover, thereturn statement is evaluated when encountered, but the result will be returned after thefinally block is executed. Additionally, if thefinally block also contains areturn statement, the value from thefinally block is returned.

    Another notable interaction is between an exception thrown from within atry block, and an exception thrown from within afinally block. If both blocks throw an exception, then the exception thrown from thefinally block will be the one that is propagated, and the exception thrown from thetry block will be used as its previous exception.

    Global exception handler

    If an exception is allowed to bubble up to the global scope, it may be caught by a global exception handler if set. Theset_exception_handler() function can set a function that will be called in place of acatch block if no other block is invoked. The effect is essentially the same as if the entire program were wrapped in atry-catch block with that function as thecatch.

    Notes

    Note:

    Internal PHP functions mainly useError reporting, only modernObject-oriented extensions use exceptions. However, errors can be easily translated to exceptions withErrorException. This technique only works with non-fatal errors, however.

    Example #1 Converting error reporting to exceptions

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

    set_error_handler('exceptions_error_handler');
    ?>

    Tip

    TheStandard PHP Library (SPL) provides a good number ofbuilt-in exceptions.

    Examples

    Example #2 Throwing an Exception

    <?php
    functioninverse($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";
    ?>

    The above example will output:

    0.2Caught exception: Division by zero.Hello World

    Example #3 Exception handling with afinally block

    <?php
    functioninverse($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";
    ?>

    The above example will output:

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

    Example #4 Interaction between thefinally block andreturn

    <?php

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

    echo
    test();
    ?>

    The above example will output:

    finally

    Example #5 Nested Exception

    <?php

    classMyExceptionextendsException{ }

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

    $foo= newTest;
    $foo->testing();

    ?>

    The above example will output:

    string(4) "foo!"

    Example #6 Multi catch exception handling

    <?php

    classMyExceptionextendsException{ }

    class
    MyOtherExceptionextendsException{ }

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

    $foo= newTest;
    $foo->testing();

    ?>

    The above example will output:

    string(11) "MyException"

    Example #7 Omitting the caught variable

    Only permitted in PHP 8.0.0 and later.

    <?php

    classSpecificExceptionextendsException{}

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

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

    The above example will output:

    A SpecificException was thrown, but we don't care about the details.

    Example #8 Throw as an expression

    Only permitted in PHP 8.0.0 and later.

    <?php

    functiontest() {
    do_something_risky() or throw newException('It did not work');
    }

    function
    do_something_risky() {
    return
    false;// Simulate failure
    }

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

    The above example will output:

    It did not work

    Example #9 Exception in try and in finally

    <?php

    try {
    try {
    throw new
    Exception(message:'Third',previous: newException('Fourth'));
    } finally {
    throw new
    Exception(message:'First',previous: newException('Second'));
    }
    } catch (
    Exception $e) {
    var_dump(
    $e->getMessage(),
    $e->getPrevious()->getMessage(),
    $e->getPrevious()->getPrevious()->getMessage(),
    $e->getPrevious()->getPrevious()->getPrevious()->getMessage(),
    );
    }

    The above example will output:

    string(5) "First"string(6) "Second"string(5) "Third"string(6) "Fourth"

    Found A Problem?

    Learn How To Improve This PageSubmit a Pull RequestReport a Bug
    add a note

    User Contributed Notes13 notes

    126
    ask at nilpo dot com
    16 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.<?phpinterfaceIException{/* Protected methods inherited from Exception class */public functiongetMessage();// Exception messagepublic functiongetCode();// User-defined Exception codepublic functiongetFile();// Source filenamepublic functiongetLine();// Source linepublic functiongetTrace();// An array of the backtrace()public functiongetTraceAsString();// Formated string of trace        /* Overrideable methods inherited from Exception class */public function__toString();// formated string for displaypublic function__construct($message=null,$code=0);}abstract classCustomExceptionextendsExceptionimplementsIException{    protected$message='Unknown exception';// Exception messageprivate$string;// Unknownprotected$code=0;// User-defined exception codeprotected$file;// Source filename of exceptionprotected$line;// Source line of exceptionprivate$trace;// Unknownpublic function__construct($message=null,$code=0)    {        if (!$message) {            throw new$this('Unknown '.get_class($this));        }parent::__construct($message,$code);    }        public function__toString()    {        returnget_class($this) ." '{$this->message}' in{$this->file}({$this->line})\n"."{$this->getTraceAsString()}";    }}?>Now you can create new exceptions in one line:<?phpclassTestExceptionextendsCustomException{}?>Here's a test that shows that all information is properly preserved throughout the backtrace.<?phpfunctionexceptionTest(){    try {        throw newTestException();    }    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}
    Johan
    14 years ago
    Custom error handling on entire pages can avoid half rendered pages for the users:<?phpob_start();try {/*contains all page logic     and throws error if needed*/...} catch (Exception $e) {ob_end_clean();displayErrorPage($e->getMessage());}?>
    tianyiw at vip dot qq dot com
    2 years ago
    Easy to understand `finally`.<?phptry {    try {        echo"before\n";1/0;        echo"after\n";    } finally {        echo"finally\n";    }} catch (\Throwable) {    echo"exception\n";}?># Print:beforefinallyexception
    Edu
    12 years ago
    The "finally" block can change the exception that has been throw by the catch block.<?phptry{        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 inHello finally Bye catch out
    Shot (Piotr Szotkowski)
    17 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).
    jlherren
    1 year ago
    As noted elsewhere, throwing an exception from the `finally` block will replace a previously thrown exception. But the original exception is magically available from the new exception's `getPrevious()`.<?phptry {    try {        throw newRuntimeException('Exception A');    } finally {        throw newRuntimeException('Exception B');    }}catch (Throwable $exception) {    echo$exception->getMessage(),"\n";// 'previous' is magically available!echo$exception->getPrevious()->getMessage(),"\n";}?>Will print:Exception BException A
    christof+php[AT]insypro.com
    8 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 caughttrigger_error($errstr,E_ERROR);                returntrue;            } else {// fallback to default php error handlerreturnfalse;            }    });    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();    }?>
    Simo
    10 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.
    daviddlowe dot flimm at gmail dot com
    8 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:<?phptry {    throw newError("foobar");// or:    // throw new Exception( "foobar" );}catch (Throwable $e) {var_export($e);}?>
    telefoontoestel at nospam dot org
    11 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.<?phptry {    echo"try block<br />";    throw newException("test");} catch (Exception $ex) {    echo"catch block<br />";} finally {    echo"finally block<br />";}// try block// catch block// finally block?><?phptry {    echo"try block<br />";    throw newException("test");} catch (Exception $ex) {    echo"catch block<br />";    exit(1);} finally {    echo"finally block<br />";}// try block// catch block?>
    mlaopane at gmail dot com
    7 years ago
    <?php/** * You can catch exceptions thrown in a deep level function */functionemployee(){    throw new\Exception("I am just an employee !");}functionmanager(){employee();}functionboss(){    try {manager();    } catch (\Exception $e) {        echo$e->getMessage();    }}boss();// output: "I am just an employee !"
    Tom Polomsk
    10 years ago
    Contrary to the documentation it is possible in PHP 5.5 and higher use only try-finally blocks without any catch block.
    Sawsan
    14 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 nametry   {   try     {      if (preg_match('/[^a-z]/i',$name))        {           throw newException("$name contains character other than a-z A-Z");       }          if(strpos(strtolower($name),'name') !==FALSE)       {          throw newException("$name contains the word name");       }       echo"The Name is valid";     }   catch(Exception $e)     {     throw newException("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/>";   }?>
    add a note
    To Top
    and to navigate •Enter to select •Esc to close •/ to open
    PressEnter without selection to search using Google

    [8]ページ先頭

    ©2009-2025 Movatter.jp