diff --git a/appendices/migration70/incompatible/error-handling.xml b/appendices/migration70/incompatible/error-handling.xml index 37e9a31525b8..5b9a2adc3345 100644 --- a/appendices/migration70/incompatible/error-handling.xml +++ b/appendices/migration70/incompatible/error-handling.xml @@ -17,12 +17,12 @@ Error exceptions). - - A fuller description of how errors operate in PHP 7 can be found - on the PHP 7 errors page. This + + A more complete description of how errors operate in PHP can be found + on the Throwable errors page. This migration guide will merely enumerate the changes that affect backward compatibility. - + diff --git a/appendices/reserved.xml b/appendices/reserved.xml index 399b84d2bc8a..5575cb663b63 100644 --- a/appendices/reserved.xml +++ b/appendices/reserved.xml @@ -55,7 +55,7 @@ <link linkend="control-structures.switch">case</link> </entry> <entry> - <link linkend="language.exceptions">catch</link> + <link linkend="control-structures.catch">catch</link> </entry> <entry> <link linkend="language.oop5.basic.class">class</link> @@ -134,7 +134,7 @@ <link linkend="language.oop5.final">final</link> </entry> <entry> - <link linkend="language.exceptions">finally</link> + <link linkend="control-structures.finally">finally</link> </entry> <entry> <link linkend="functions.arrow">fn</link> (as of PHP 7.4) @@ -236,13 +236,13 @@ <link linkend="control-structures.switch">switch</link> </entry> <entry> - <link linkend="language.exceptions">throw</link> + <link linkend="control-structures.throw">throw</link> </entry> <entry> <link linkend="language.oop5.traits">trait</link> </entry> <entry> - <link linkend="language.exceptions">try</link> + <link linkend="control-structures.try">try</link> </entry> <entry> <function>unset</function> diff --git a/appendices/tokens.xml b/appendices/tokens.xml index 7a4223faba29..30a4521916ca 100644 --- a/appendices/tokens.xml +++ b/appendices/tokens.xml @@ -180,7 +180,7 @@ defined('T_FN') || define('T_FN', 10001); (<type>int</type>) </entry> <entry>catch</entry> - <entry><xref linkend="language.exceptions"/></entry> + <entry><xref linkend="control-structures.catch"/></entry> </row> <row xml:id="constant.t-class"> <entry> @@ -557,7 +557,7 @@ defined('T_FN') || define('T_FN', 10001); (<type>int</type>) </entry> <entry>finally</entry> - <entry><xref linkend="language.exceptions"/></entry> + <entry><xref linkend="control-structures.finally"/></entry> </row> <row xml:id="constant.t-fn"> <entry> @@ -1255,7 +1255,7 @@ defined('T_FN') || define('T_FN', 10001); (<type>int</type>) </entry> <entry>throw</entry> - <entry><xref linkend="language.exceptions"/></entry> + <entry><xref linkend="control-structures.throw"/></entry> </row> <row xml:id="constant.t-trait"> <entry> @@ -1279,7 +1279,7 @@ defined('T_FN') || define('T_FN', 10001); (<type>int</type>) </entry> <entry>try</entry> - <entry><xref linkend="language.exceptions"/></entry> + <entry><xref linkend="control-structures.try"/></entry> </row> <row xml:id="constant.t-unset"> <entry> diff --git a/entities/entities.php.ent b/entities/entities.php.ent index 8736cb6e803d..f83651342e48 100644 --- a/entities/entities.php.ent +++ b/entities/entities.php.ent @@ -21,7 +21,7 @@ There are a few <filename> tossed near and there. <entity name="callback.cmp"><methodsynopsis><type>int</type><methodname><replaceable>callback</replaceable></methodname><methodparam><type>mixed</type><parameter>a</parameter></methodparam><methodparam><type>mixed</type><parameter>b</parameter></methodparam></methodsynopsis></entity> -<entity name="catch"><link linkend="language.exceptions.catch"><literal>catch</literal></link></entity> +<entity name="catch"><link linkend="control-structures.catch"><literal>catch</literal></link></entity> <entity name="const"><link linkend="language.constants.syntax"><literal>const</literal></link></entity> @@ -29,7 +29,7 @@ There are a few <filename> tossed near and there. <entity name="false"><constant>false</constant></entity> -<entity name="finally"><link linkend="language.exceptions.finally"><literal>finally</literal></link></entity> +<entity name="finally"><link linkend="control-structures.finally"><literal>finally</literal></link></entity> <entity name="float"><type>float</type></entity> @@ -71,11 +71,11 @@ There are a few <filename> tossed near and there. <entity name="string"><type>string</type></entity> -<entity name="throw"><link linkend="language.exceptions"><literal>throw</literal></link></entity> +<entity name="throw"><link linkend="control-structures.throw"><literal>throw</literal></link></entity> <entity name="true"><constant>true</constant></entity> -<entity name="try"><link linkend="language.exceptions"><literal>try</literal></link></entity> +<entity name="try"><link linkend="control-structures.try"><literal>try</literal></link></entity> <entity name="use.namespace"><link linkend="language.namespaces.importing"><literal>use</literal></link></entity> diff --git a/language/control-structures.xml b/language/control-structures.xml index b9a6b334e9b5..437eb3ea95af 100644 --- a/language/control-structures.xml +++ b/language/control-structures.xml @@ -54,6 +54,9 @@ &language.control-structures.require-once; &language.control-structures.include-once; &language.control-structures.goto; + &language.control-structures.throw; + &language.control-structures.try-catch; + &language.control-structures.finally; </chapter> diff --git a/language/control-structures/finally.xml b/language/control-structures/finally.xml new file mode 100644 index 000000000000..f2146d26696b --- /dev/null +++ b/language/control-structures/finally.xml @@ -0,0 +1,488 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- $Revision$ --> +<sect1 xml:id="control-structures.finally" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>finally + + + 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, even if a &return; or &yield; statement is encountered, + or if a Throwable error is not caught or is rethrown. + It will be executed prior to resuming the normal execution flow. + The only exception to this rule is when the script is terminated abruptly, + such as by a call to exit or by a fatal error + (for example when the maximum execution time is exceeded). + + + <exceptionname>Throwable</exceptionname> error handling with a &finally; block + +getMessage(), "\n"; +} finally { + echo "First finally.\n"; +} + +try { + echo inverse(0) . "\n"; +} catch (\DivisionByZeroError $e) { + echo 'Caught error: ', $e->getMessage(), "\n"; +} finally { + echo "Second finally.\n"; +} + +// Continue execution +echo "Hello World\n"; +]]> + + &example.outputs.8; + + + + + + + When the call stack is unwound after a Throwable error + has been thrown, all &finally; blocks it encounters along the way will be executed. + In other words, nested &finally; blocks are executed even if the + Throwable error is not caught by an adjacent + &catch; block. + + + All &finally; block will be executed + + + + &example.outputs; + + + + + + + Interaction between a &finally; block and a &return; statement + + One notable interaction is between the &finally; block and a &return; statement. + If a &return; statement is encountered inside either the &try; or the &catch; blocks, + the &finally; block will still be executed. Moreover, the &return; statement is + evaluated when encountered, but the result will be returned after the &finally; block + is executed. Additionally, if the &finally; block also contains a &return; statement, + the value from the &finally; block is returned. + + + Interaction between &return; in &finally; block and a previous &return; + + + + &example.outputs; + + + + + + Interaction between the &finally; block and &return; + + + + &example.outputs; + + + + + + + + Interaction between a &finally; block and an exception thrown in a &try; block + + If both the &try; block and the &finally; block throw an exception, + the exception thrown from the &finally; block is the one that is propagated, + and the exception thrown from the &try; block will be used as its previous exception. + + + Exception in try and in finally + +getMessage(), + $e->getPrevious()->getMessage(), + $e->getPrevious()->getPrevious()->getMessage(), + $e->getPrevious()->getPrevious()->getPrevious()->getMessage(), + ); +} +]]> + + &example.outputs; + + + + + + + + + Behaviour of a &finally; block in a + <link linkend="language.generators">Generator</link> + + + + If during the traversal of a generator a Throwable + error is thrown, the &finally; within the generator will be executed, + as it is the previous element of the call stack. + + + + &finally; block being run when an <exceptionname>Exception</exceptionname> + has been thrown + + + + + &example.outputs.similar; + + + + + + + It is possible to &yield; within a &finally; block but if a + Throwable error occurs and is not caught within + the &foreach; a Cannot yield from finally in a force-closed + generator Error is thrown. + + + + Error when &yield;ing in &finally; block when an <exceptionname>Exception</exceptionname> + has been thrown + + + + + &example.outputs.similar; + + + + + + + + Interaction between a &finally; block and a call to <function>exit</function> + + When exit is called within a &try; or a &catch; block + all &finally; blocks are skipped. + + + Interaction between &finally; block and <function>exit</function> called in &try; block + + + + &example.outputs; + + + + + + Interaction between &finally; block and <function>exit</function> called in &catch; block + + + + &example.outputs; + + + + + + All &finally; blocks are skipped when <function>exit</function> is called + + + + &example.outputs; + + + + + + + When exit is called within a &finally; block, + all other outer &finally; blocks are skipped. + + + Skipping outer &finally; block by calling <function>exit</function> + + + + &example.outputs; + + + + + + + Edge case of calling <function>exit</function> in a &foreach; over a generator + + This one edge case behaviour is highly dependent on which version of PHP + the code is executed. + + + + + + + + Output of the above example prior to PHP 7.1.14, in PHP 7.2.0 and 7.2.1, + and as of PHP 8.0.0 + + + + + + Output of the above example as of PHP 7.1.14 and 7.2.2, + and prior to PHP 8.0.0 + + + + + + + + diff --git a/language/control-structures/throw.xml b/language/control-structures/throw.xml new file mode 100644 index 000000000000..9bd0b2f993a1 --- /dev/null +++ b/language/control-structures/throw.xml @@ -0,0 +1,135 @@ + + + + throw + + + The &throw; keyword is an expression and may be used in any expression context. + It takes an instance of a Throwable object as an + argument. + + + + Prior to PHP 8.0, the &throw; keyword was a statement and not an expression. + + + + Attempting to &throw; a non-Throwable object will + throw an Error. + + + Throwing a non-<exceptionname>Throwable</exceptionname> object + + + + &example.outputs.similar; + + + + + + + + After using &throw; the normal flow of execution is halted and the call stack + is unwound until the object is caught by a &catch; block or the global scope + is reached. In the latter case, the program is terminated with + a fatal error containing the stack trace indicating where the + Throwable object has been thrown. + + + Throwing an Exception in the global scope + + + + &example.outputs.similar; + + + + + + Throwing an Exception in a function + + + + &example.outputs.similar; + + + + + + + As &throw; is an expression it can be used to branch out on the result + of another expression if its value is inappropriate. + + + Using throw as an expression + Only permitted as of PHP 8.0.0. + +getMessage(); +} +]]> + + &example.outputs; + + + + + + + It is possible to handle a thrown Throwable by using + a try-catch block. + See the error handling + section for more information. + + diff --git a/language/control-structures/try-catch.xml b/language/control-structures/try-catch.xml new file mode 100644 index 000000000000..c372bf09061d --- /dev/null +++ b/language/control-structures/try-catch.xml @@ -0,0 +1,235 @@ + + + + Try...Catch + + try + + + A &try; block delimits a segment of code which might &throw; + a Throwable error that needs handling. + A &try; block must have at least one corresponding + &catch; or &finally; block. + + + When a Throwable error is thrown in a &try; block + PHP will attempt to find the first matching &catch; block to handle the + error. If none can be found, it will unwind the call stack until one is found or a global error handler is reached. + + + + It's possible to add a handler for any uncaught + Throwable with + set_exception_handler. + This is similar to wrapping the entire code in a &try;-&catch; block. + + + + + catch + + + A &catch; block defines how to respond to a thrown Throwable error. + It specifies one or more subclasses of Throwable + (most commonly Exception) it can handle, and + optionally a variable to which to assign the exception. + + + The first &catch; block + that matches the class of the thrown Throwable + object will handle the error. + Normal execution resumes after the &catch; block without entering any other matching &catch; blocks. + + + Catching an Exception + +getMessage(), "\n"; +} + +// Continue execution +echo "Hello World\n"; +]]> + + &example.outputs; + + + + + + + As of PHP 7.1.0, a &catch; block may specify a union of + Throwable subclasses that the block should handle + using the pipe (|) character. This is useful for when + different exceptions from different class hierarchies are handled the same. + + + Catching a union of classes to handle + +testing(); +]]> + + &example.outputs; + + + + + + + Multiple &catch; blocks can be used to handle different classes of + Throwable errors in different ways. + Normal execution (when no error is thrown within the &try; block) will + continue after that last &catch; block defined in sequence. + + + Multiple catch blocks + + + + + + + Throwables can be &throw;n (or re-thrown) within a &catch; block. + If nothing is thrown, the execution resumes as normal. + + + Nested Exception + +getMessage()); + } + } +} + +$foo = new Test; +$foo->testing(); +]]> + + &example.outputs; + + + + + + + Throwing an object inside a &catch; block will not + be caught by an adjacent &catch; block. + + + Sequential catch blocks + + + + &example.outputs.similar; + + + + + + + + As of PHP 8.0.0, the variable name for a caught + Throwable is optional. + If not specified, the &catch; block will still execute but will not + have access to the thrown object. + + + Omitting the caught variable + Only permitted as of PHP 8.0.0. + + + + &example.outputs; + + + + + + diff --git a/language/error-handling.xml b/language/error-handling.xml new file mode 100644 index 000000000000..2ff1549d27d3 --- /dev/null +++ b/language/error-handling.xml @@ -0,0 +1,357 @@ + + + + Error Handling + + See also the Exception class + + + Errors are a normal part of the development and life cycle of an application. + As such PHP provides multiple ways to inform and deal with errors. + + + PHP has two main mechanisms for reporting errors: + + + + Throwable errors, which are further split into + programming errors via the Error + class hierarchy and recoverable errors via the + Exception class hierarchy. + + + + + Diagnostic errors which are classified into different + severities. + + + + + + + <exceptionname>Throwable</exceptionname> errors + + + A Throwable error is an execution event which disrupts + the normal flow of instructions. When a Throwable error + is &throw;n, be that by the engine or manually, it will unwind the call stack + until it is caught by a &catch; block or the global scope is reached, in which + case the program is terminated with a fatal error. + All &finally; blocks it encounters along the way will be executed. + + + To throw a Throwable error from within PHP code, one + must use the &throw; keyword followed by an instance of the + Error or Exception class or + a subclass of one of them. + Trying to throw an object that is not will result in an + Error being thrown with the following message: + Cannot throw objects that do not implement Throwable. + + + + The Standard PHP Library (SPL) provides + various built-in exceptions. + And it's possible to create custom exceptions by + extending the + Exception class. + + + + It is possible to handle a Throwable error within PHP + by surrounding the code susceptible to throw an error in a &try; block. + A &try; block must have at least one corresponding &catch; or &finally; block. + + + + It is not recommended to catch Error + objects as those signal a programming error. + + + + + Throwable objects cannot be cloned. + Attempting to clone such an + object throws an Error, even if a subclass declares + its own __clone() method, with + the following message: + Trying to clone an uncloneable object of class Exception. + + + + + <literal>Global exception handler</literal> + + It's possible to add a handler for any uncaught + Throwable with + set_exception_handler. + This is similar to wrapping the entire code in a &try;-&catch; block, + except that execution does not resume afterwards: the script + terminates once the handler returns. + + + + + Extending Exceptions + + A user-defined exception can be defined by extending the built-in + Exception class. + To see which methods and properties are accessible within a child class + derived from Exception visit its page. + + + If a class extends the built-in Exception class and + re-defines the constructor, + it is highly recommended that it also call parent::__construct() + to ensure all available data has been properly assigned. + The __toString() method can be overridden + to provide a custom output when the object is used as a string. + + + Extending <exceptionname>Exception</exceptionname> + +code}]: {$this->message}\n"; + } + + public function customFunction() { + echo "A custom function for this type of exception\n"; + } +} + +try { + throw new CustomException("Something happened", 5); +} catch (CustomException $e) { + echo "Caught custom exception\n", $e; + $e->customFunction(); +} +]]> + + &example.outputs; + + + + + + + + <exceptionname>Throwable</exceptionname> hierarchy + + + + Throwable + + + Error + + + ArithmeticError + + + DivisionByZeroError + + + + + AssertionError + + + CompileError + + + ParseError + + + + + TypeError + + + ArgumentCountError + + + + + ValueError + + + UnhandledMatchError + + + FiberError + + + + + Exception + + + + + + + The Exception class has many subclasses, + among them the SPL exceptions and + those defined by extensions. + + + + + + Diagnostic errors + + Diagnostic errors, also known as traditional errors, are used to signal a + number of different conditions, and can be displayed and/or logged as required. + By default PHP will report all diagnostic errors. (Prior to PHP 8.0, + E_NOTICE and E_DEPRECATED + diagnostics were not reported by default.) + + + In contrast to Throwable errors, most diagnostic + errors do not disrupt the normal flow of execution. + Fatal diagnostics, such as E_ERROR, terminate the script. + + + Which diagnostics are reported and which are ignored is controlled by the + error_reporting + &php.ini; directive, or at runtime by calling error_reporting. + It is strongly recommended that the configuration directive be set, + as some errors can occur before execution of your script begins. + + + + In a development environment, + error_reporting + should always be set to E_ALL to be aware of and fix + issues raised by PHP. + However, in production the level of verbosity could be reduced to + E_ALL & ~E_NOTICE & ~E_DEPRECATED, but in many cases + E_ALL is still appropriate, as it may provide early + warning of potential issues. + + + + + What happens to the diagnostics depends on two further &php.ini; directives. + display_errors + controls whether the diagnostic is shown as part of the script's output. + This should always be disabled in a production environment, as it can include + confidential information such as database passwords, but is often useful to + enable in development, as it ensures immediate reporting of issues. + + + + In addition to displaying errors, PHP can log diagnostics when the + log_errors + directive is enabled. This will log any diagnostic to the file or syslog + defined by + error_log. + This can be extremely useful in a production environment, as diagnostics are + logged when they occur and can then generate reports based on those logs. + + + Individual diagnostics can be suppressed using the + @ operator. + + + + + Prior to PHP 8.0.0 it was possible to suppress critical diagnostics that + would terminate the execution of the PHP script. + + + + + + Diagnostics can be added, removed, have their severity altered or be + elevated to a Throwable error in between PHP versions. + + + + + User defined diagnostic handler + + + If PHP's default diagnostic handling is inadequate, + it is possible to override the default diagnostic handler with a custom one + which is set using set_error_handler. + Some diagnostics, such as E_ERROR and + E_PARSE, cannot be handled this way (see + set_error_handler for the full list). + The others can be handled in various ways. For example, this can be used to show a custom + error page to the user and then report more directly than via a log, such + as by sending an e-mail. + + + + Another typical usage is to elevate diagnostic errors to exceptions with + ErrorException. + + + Elevating diagnostic errors to exceptions + + + + + + It is important to verify that the severity is included in the current + list of reportable diagnostics, otherwise the + @ operator + will be broken, as an exception will be thrown for a suppressed diagnostic. + + + + + + + + &reftitle.changelog; + + + + + &Version; + &Description; + + + + + 8.5.0 + + Fatal errors (such as an exceeded maximum execution time) now include + a stack trace in their error message. + + + + + + + + diff --git a/language/errors.xml b/language/errors.xml deleted file mode 100644 index 0c5edd64cf82..000000000000 --- a/language/errors.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - Errors - - - Introduction - - - Sadly, no matter how careful we are when writing our code, errors are a - fact of life. PHP will report errors, warnings and notices for many common - coding and runtime problems, and knowing how to detect and handle these - errors will make debugging much easier. - - - - &language.errors.basics; - &language.errors.php7; - - - diff --git a/language/errors/basics.xml b/language/errors/basics.xml deleted file mode 100644 index 5b31f247e8d7..000000000000 --- a/language/errors/basics.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - Basics - - - PHP reports errors in response to a number of internal error conditions. - These may be used to signal a number of different conditions, and can be - displayed and/or logged as required. - - - - Every error that PHP generates includes a type. A - list of these error types is available, - along with a short description of their behaviour and how they can be - caused. - - - - Handling errors with PHP - - - If no error handler is set, then PHP will handle any errors that occur - according to its configuration. Which errors are reported and which are - ignored is controlled by the - error_reporting - php.ini directive, or at runtime by calling - error_reporting. It is strongly recommended that the - configuration directive be set, however, as some errors can occur before - execution of your script begins. - - - - In a development environment, you should always set - error_reporting - to E_ALL, as you need to be aware of and fix the - issues raised by PHP. In production, you may wish to set this to a less - verbose level such as - E_ALL & ~E_NOTICE & ~E_DEPRECATED, but - in many cases E_ALL is also appropriate, as it may - provide early warning of potential issues. - - - - What PHP does with these errors depends on two further php.ini directives. - display_errors - controls whether the error is shown as part of the script's output. This - should always be disabled in a production environment, as it can include - confidential information such as database passwords, but is often useful to - enable in development, as it ensures immediate reporting of issues. - - - - In addition to displaying errors, PHP can log errors when the - log_errors - directive is enabled. This will log any errors to the file or syslog - defined by - error_log. This - can be extremely useful in a production environment, as you can log errors - that occur and then generate reports based on those errors. - - - - - User error handlers - - - If PHP's default error handling is inadequate, you can also handle many - types of error with your own custom error handler by installing it with - set_error_handler. While some error types cannot be - handled this way, those that can be handled can then be handled in the way - that your script sees fit: for example, this can be used to show a custom - error page to the user and then report more directly than via a log, such - as by sending an e-mail. - - - - - &reftitle.changelog; - - - - - &Version; - &Description; - - - - - 8.5.0 - - Fatal errors (such as an exceeded maximum execution time) now include - a stack trace in their error message. - - - - - - - - - - - diff --git a/language/errors/php7.xml b/language/errors/php7.xml deleted file mode 100644 index 55400297825c..000000000000 --- a/language/errors/php7.xml +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Errors in PHP 7 - - - PHP 7 changes how most errors are reported by PHP. Instead of reporting - errors through the traditional error reporting mechanism used by PHP 5, most - errors are now reported by throwing Error exceptions. - - - - As with normal exceptions, these Error exceptions - will bubble up until they reach the first matching - catch - block. If there are no matching blocks, then any default exception handler - installed with set_exception_handler will be called, - and if there is no default exception handler, then the exception will be - converted to a fatal error and will be handled like a traditional error. - - - - As the Error hierarchy does not inherit from - Exception, code that uses - catch (Exception $e) { ... } blocks to handle uncaught - exceptions in PHP 5 will find that these Errors are - not caught by these blocks. Either a catch (Error $e) { ... } - block or a set_exception_handler handler is required. - - - - <classname>Error</classname> hierarchy - - - - Throwable - - - Error - - - ArithmeticError - - - DivisionByZeroError - - - - - AssertionError - - - CompileError - - - ParseError - - - - - TypeError - - - ArgumentCountError - - - - - ValueError - - - UnhandledMatchError - - - FiberError - - - RequestParseBodyException - - - - - Exception - - - ... - - - - - - - - - - - diff --git a/language/exceptions.xml b/language/exceptions.xml deleted file mode 100644 index c284e26c36d5..000000000000 --- a/language/exceptions.xml +++ /dev/null @@ -1,591 +0,0 @@ - - - - Exceptions - - See also the Exception class - - - PHP has an exception model similar to that of other programming - languages. An exception can be &throw;n, and caught ("&catch;ed") within - PHP. Code may be surrounded in a &try; block, to facilitate the catching - of potential exceptions. Each &try; must have at least one corresponding - &catch; or &finally; block. - - - If an exception is thrown and its current function scope has no &catch; - block, the exception will "bubble up" the call stack to the calling - function until it finds a matching &catch; block. All &finally; 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 matching &catch; block, the program will - terminate with a fatal error unless a global exception handler has been set. - - - The thrown object must be an &instanceof; Throwable. - Trying to throw an object that is not will result in a PHP Fatal Error. - - - As of PHP 8.0.0, the &throw; 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. - - - - <literal>catch</literal> - - A &catch; block defines how to respond to a thrown exception. A &catch; - 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 first &catch; block a thrown exception - or error encounters that matches the type of the thrown object will handle - the object. - - - Multiple &catch; blocks can be used to catch different classes of - exceptions. Normal execution (when no exception is thrown within the &try; - block) will continue after that last &catch; block defined in sequence. - Exceptions can be &throw;n (or re-thrown) within a &catch; block. If not, - execution will continue after the &catch; 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 matching &catch; 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 with set_exception_handler. - - - As of PHP 7.1.0, a &catch; 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, the &catch; block will still execute but will not - have access to the thrown object. - - - - - <literal>finally</literal> - - 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. - - - One notable interaction is between the &finally; block and a &return; statement. - If a &return; statement is encountered inside either the &try; or the &catch; blocks, - the &finally; block will still be executed. Moreover, the &return; statement is - evaluated when encountered, but the result will be returned after the &finally; block - is executed. Additionally, if the &finally; block also contains a &return; statement, - the value from the &finally; block is returned. - - - Another notable interaction is between an exception thrown from within a &try; block, - and an exception thrown from within a &finally; block. If both blocks throw an exception, - then the exception thrown from the &finally; block will be the one that is propagated, - and the exception thrown from the &try; 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. The set_exception_handler - function can set a function that will be called in place of a &catch; block if no - other block is invoked. The effect is essentially the same as if the entire program - were wrapped in a &try;-&catch; block with that function as the &catch;. - - - - - &reftitle.notes; - - - - Internal PHP functions mainly use - Error reporting, only modern - Object-oriented - extensions use exceptions. However, errors can be easily translated to - exceptions with ErrorException. - This technique only works with non-fatal errors, however. - - - Converting error reporting to exceptions - - - - - - - - The Standard PHP Library (SPL) provides - a good number of built-in - exceptions. - - - - - - &reftitle.examples; - - - Throwing an Exception - -getMessage(), "\n"; -} - -// Continue execution -echo "Hello World\n"; -]]> - - &example.outputs; - - - - - - Exception handling with a &finally; block - -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"; -]]> - - &example.outputs; - - - - - - Interaction between the &finally; block and &return; - - - - &example.outputs; - - - - - - Nested Exception - -getMessage()); - } - } -} - -$foo = new Test; -$foo->testing(); -]]> - - &example.outputs; - - - - - - Multi catch exception handling - -testing(); -]]> - - &example.outputs; - - - - - - Omitting the caught variable - Only permitted in PHP 8.0.0 and later. - - - - &example.outputs; - - - - - - Throw as an expression - Only permitted in PHP 8.0.0 and later. - -getMessage(); -} -]]> - - &example.outputs; - - - - - - Exception in try and in finally - -getMessage(), - $e->getPrevious()->getMessage(), - $e->getPrevious()->getPrevious()->getMessage(), - $e->getPrevious()->getPrevious()->getPrevious()->getMessage(), - ); -} -]]> - - &example.outputs; - - - - - - - - Extending Exceptions - - A User defined Exception class can be defined by extending the built-in - Exception class. The members and properties below, show what is accessible - within the child class that derives from the built-in Exception class. - - - The Built in Exception class - - - - - - If a class extends the built-in Exception class and re-defines the constructor, it is highly recommended - that it also call parent::__construct() - to ensure all available data has been properly assigned. The __toString() method can be overridden - to provide a custom output when the object is presented as a string. - - - - Exceptions cannot be cloned. Attempting to clone an exception throws an - Error, even if a subclass declares its own - __clone() method. - - - - Extending the Exception class - - code}]: {$this->message}\n"; - } - - public function customFunction() { - echo "A custom function for this type of exception\n"; - } -} - - -/** - * Create a class to test the exception - */ -class TestException -{ - public $var; - - const THROW_NONE = 0; - const THROW_CUSTOM = 1; - const THROW_DEFAULT = 2; - - function __construct($avalue = self::THROW_NONE) { - - switch ($avalue) { - case self::THROW_CUSTOM: - // throw custom exception - throw new MyException('1 is an invalid parameter', 5); - break; - - case self::THROW_DEFAULT: - // throw default one. - throw new Exception('2 is not allowed as a parameter', 6); - break; - - default: - // No exception, object will be created. - $this->var = $avalue; - break; - } - } -} - - -echo "# Example 1\n"; -try { - $o = new TestException(TestException::THROW_CUSTOM); -} catch (MyException $e) { // Will be caught - echo "Caught my exception\n", $e; - $e->customFunction(); -} catch (Exception $e) { // Skipped - echo "Caught Default Exception\n", $e; -} - -// Continue execution -var_dump($o); // Null - - -echo "\n\n# Example 2\n"; -try { - $o = new TestException(TestException::THROW_DEFAULT); -} catch (MyException $e) { // Doesn't match this type - echo "Caught my exception\n", $e; - $e->customFunction(); -} catch (Exception $e) { // Will be caught - echo "Caught Default Exception\n", $e; -} - -// Continue execution -var_dump($o); // Null - - -echo "\n\n# Example 3\n"; -try { - $o = new TestException(TestException::THROW_CUSTOM); -} catch (Exception $e) { // Will be caught - echo "Default Exception caught\n", $e; -} - -// Continue execution -var_dump($o); // Null - - -echo "\n\n# Example 4\n"; -try { - $o = new TestException(); -} catch (Exception $e) { // Skipped, no exception - echo "Default Exception caught\n", $e; -} - -// Continue execution -var_dump($o); // TestException -]]> - - - - - - - diff --git a/language/oop5/basic.xml b/language/oop5/basic.xml index ea87be554544..bdf64c7d676c 100644 --- a/language/oop5/basic.xml +++ b/language/oop5/basic.xml @@ -197,14 +197,14 @@ readonly class Foo new - + To create an instance of a class, the new keyword must be used. An object will always be created unless the object has a constructor defined that throws an - exception on error. Classes + Exception on error. Classes should be defined before instantiation (and in some cases this is a requirement). - + If a variable containing a string with the name of a class is used with new, a new instance of that class will be created. If diff --git a/language/oop5/changelog.xml b/language/oop5/changelog.xml index 9580aecbd184..bccee0a60328 100644 --- a/language/oop5/changelog.xml +++ b/language/oop5/changelog.xml @@ -213,7 +213,7 @@ 5.5.0 - Added: finally to handle exceptions. + Added: finally to handle exceptions. @@ -271,9 +271,9 @@ Changed: Prior to 5.3.0, exceptions thrown in the __autoload function could not be - caught in the catch block, and + caught in the catch block, and would result in a fatal error. Exceptions now thrown in the __autoload function - can be caught in the catch block, with + can be caught in the catch block, with one provision. If throwing a custom exception, then the custom exception class must be available. The __autoload function may be used recursively to autoload the custom exception class. diff --git a/language/operators/precedence.xml b/language/operators/precedence.xml index 9d4f02925ef5..2dfbdd8963a3 100644 --- a/language/operators/precedence.xml +++ b/language/operators/precedence.xml @@ -320,7 +320,7 @@ (n/a) throw - throw + throw diff --git a/language/predefined/exceptions.xml b/language/predefined/exceptions.xml index 14a3f914d56c..c963e3d2a0e0 100644 --- a/language/predefined/exceptions.xml +++ b/language/predefined/exceptions.xml @@ -15,7 +15,7 @@ &language.predefined.closedgeneratorexception; + language/error-handling.xml. --> &language.predefined.error; &language.predefined.argumentcounterror; &language.predefined.arithmeticerror; diff --git a/manual.xml b/manual.xml index 84c6986aa404..f393b9f67120 100644 --- a/manual.xml +++ b/manual.xml @@ -52,8 +52,7 @@ &language.oop5; &language.namespaces; &language.enumerations; - &language.errors; - &language.exceptions; + &language.error-handling; &language.fibers; &language.generators; &language.attributes; diff --git a/reference/dom/domexception.xml b/reference/dom/domexception.xml index bcea4a042ff6..e6488c45735a 100644 --- a/reference/dom/domexception.xml +++ b/reference/dom/domexception.xml @@ -25,9 +25,9 @@ FIXME: Remove me once you perform substitutions This class is aliased as Dom\Exception in the Dom namespace. - - See also . - + + See also . + diff --git a/reference/errorfunc/functions/get-exception-handler.xml b/reference/errorfunc/functions/get-exception-handler.xml index 919e03687b31..a24d27f44649 100644 --- a/reference/errorfunc/functions/get-exception-handler.xml +++ b/reference/errorfunc/functions/get-exception-handler.xml @@ -91,7 +91,7 @@ if (!function_exists('get_exception_handler')) { restore_exception_handler restore_error_handler error_reporting - Exceptions + Exceptions diff --git a/reference/errorfunc/functions/set-exception-handler.xml b/reference/errorfunc/functions/set-exception-handler.xml index df06f4462c14..107f531f7c2a 100644 --- a/reference/errorfunc/functions/set-exception-handler.xml +++ b/reference/errorfunc/functions/set-exception-handler.xml @@ -149,7 +149,7 @@ echo "Not Executed\n"; restore_exception_handler restore_error_handler error_reporting - Exceptions + Exceptions diff --git a/reference/pdo/connections.xml b/reference/pdo/connections.xml index 6602616cc3b4..3bfb98ae4661 100644 --- a/reference/pdo/connections.xml +++ b/reference/pdo/connections.xml @@ -44,8 +44,8 @@ try { - - Just like any other exception, + + Just like any other exception, PDOException could be caught either explicitly, via a &catch; statement, or implicitly via set_exception_handler. Otherwise, the default behaviour of converting an uncaught exception to a @@ -54,7 +54,7 @@ try { As such, the &php.ini; option display_errors should be set to 0 on a production server. - + Upon successful connection to the database, an instance of the PDO class diff --git a/reference/pdo/error-handling.xml b/reference/pdo/error-handling.xml index 83bb4c22d0fd..64e0e72c867c 100644 --- a/reference/pdo/error-handling.xml +++ b/reference/pdo/error-handling.xml @@ -57,10 +57,10 @@ with less code/nesting than by running in silent mode and explicitly checking the return value of each database call. - - See Exceptions for more - information about Exceptions in PHP. - + + See for more + information about handling Exceptions in PHP. + diff --git a/reference/pdo/pdoexception.xml b/reference/pdo/pdoexception.xml index 1d702df4c231..1a3fefe4bb62 100644 --- a/reference/pdo/pdoexception.xml +++ b/reference/pdo/pdoexception.xml @@ -8,12 +8,13 @@
&reftitle.intro; - + Represents an error raised by PDO. You should not throw a PDOException from your own code. - See Exceptions for more - information about Exceptions in PHP. - + + + See also . +
diff --git a/reference/snmp/snmpexception.xml b/reference/snmp/snmpexception.xml index 8f91ea641c60..36834097cae9 100644 --- a/reference/snmp/snmpexception.xml +++ b/reference/snmp/snmpexception.xml @@ -11,7 +11,7 @@ Represents an error raised by SNMP. You should not throw a SNMPException from your own code. - See Exceptions for more + See Exceptions for more information about Exceptions in PHP.