mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-15 16:38:54 +00:00

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@330826 c90b9560-bf6c-de11-be94-00142212c4b1
402 lines
11 KiB
XML
402 lines
11 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<chapter xml:id="language.exceptions" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Exceptions</title>
|
|
|
|
<para>
|
|
PHP 5 has an exception model similar to that of other programming languages.
|
|
An exception can be <literal>throw</literal>n, and caught
|
|
("<literal>catch</literal>ed") within PHP. Code may be surrounded in a
|
|
<literal>try</literal> block, to facilitate the catching of potential
|
|
exceptions. Each <literal>try</literal> must have at least one
|
|
corresponding <literal>catch</literal> block. Multiple
|
|
<literal>catch</literal> blocks can be used to catch different classes of
|
|
exceptions. Normal execution (when no exception is thrown within the
|
|
<literal>try</literal> block, or when a <literal>catch</literal> matching
|
|
the thrown exception's class is not present) will continue after that last
|
|
<literal>catch</literal> block defined in sequence. Exceptions can be
|
|
<literal>throw</literal>n (or re-thrown) within a <literal>catch</literal> block.
|
|
</para>
|
|
<para>
|
|
When an exception is thrown, code following the statement will not be
|
|
executed, and PHP will attempt to find the first matching
|
|
<literal>catch</literal> block. If an
|
|
exception is not caught, a PHP Fatal Error will be issued with an
|
|
"<literal>Uncaught Exception ...</literal>" message, unless a handler has
|
|
been defined with <function>set_exception_handler</function>.
|
|
</para>
|
|
<para>
|
|
In PHP 5.5 and later, a <literal>finally</literal> block may also be
|
|
specified after the <literal>catch</literal> blocks. Code within the
|
|
<literal>finally</literal> block will always be executed after the
|
|
<literal>try</literal> and <literal>catch</literal> blocks, regardless of
|
|
whether an exception has been thrown, and before normal execution resumes.
|
|
</para>
|
|
<para>
|
|
The thrown object must be an instance of the <classname>Exception</classname>
|
|
class or a subclass of <classname>Exception</classname>. Trying to throw an
|
|
object that is not will result in a PHP Fatal Error.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Internal PHP functions mainly use
|
|
<link linkend="ini.error-reporting">Error reporting</link>, only modern
|
|
<link linkend="language.oop5">Object oriented</link>
|
|
extensions use exceptions. However, errors can be simply translated to
|
|
exceptions with <link linkend="class.errorexception">ErrorException</link>.
|
|
</para>
|
|
</note>
|
|
<tip>
|
|
<para>
|
|
The <link linkend="intro.spl">Standard PHP Library (SPL)</link> provides a
|
|
good number of <link linkend="spl.exceptions">built-in exceptions</link>.
|
|
</para>
|
|
</tip>
|
|
<example>
|
|
<title>Throwing an Exception</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function inverse($x) {
|
|
if (!$x) {
|
|
throw new Exception('Division by zero.');
|
|
}
|
|
return 1/$x;
|
|
}
|
|
|
|
try {
|
|
echo inverse(5) . "\n";
|
|
echo inverse(0) . "\n";
|
|
} catch (Exception $e) {
|
|
echo 'Caught exception: ', $e->getMessage(), "\n";
|
|
}
|
|
|
|
// Continue execution
|
|
echo "Hello World\n";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
0.2
|
|
Caught exception: Division by zero.
|
|
Hello World
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<example>
|
|
<title>Exception handling with a <literal>finally</literal> block</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function inverse($x) {
|
|
if (!$x) {
|
|
throw new Exception('Division by zero.');
|
|
}
|
|
return 1/$x;
|
|
}
|
|
|
|
try {
|
|
echo inverse(5) . "\n";
|
|
} catch (Exception $e) {
|
|
echo 'Caught exception: ', $e->getMessage(), "\n";
|
|
} finally {
|
|
echo "First finally.\n";
|
|
}
|
|
|
|
try {
|
|
echo inverse(0) . "\n";
|
|
} catch (Exception $e) {
|
|
echo 'Caught exception: ', $e->getMessage(), "\n";
|
|
} finally {
|
|
echo "Second finally.\n";
|
|
}
|
|
|
|
// Continue execution
|
|
echo "Hello World\n";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
0.2
|
|
First finally.
|
|
Caught exception: Division by zero.
|
|
Second finally.
|
|
Hello World
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<example>
|
|
<title>Nested Exception</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class MyException extends Exception { }
|
|
|
|
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 = new Test;
|
|
$foo->testing();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
string(4) "foo!"
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<sect1 xml:id="language.exceptions.extending">
|
|
<title>Extending Exceptions</title>
|
|
<para>
|
|
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.
|
|
</para>
|
|
<example>
|
|
<title>The Built in Exception class</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Exception
|
|
{
|
|
protected $message = 'Unknown exception'; // exception message
|
|
private $string; // __toString cache
|
|
protected $code = 0; // user defined exception code
|
|
protected $file; // source filename of exception
|
|
protected $line; // source line of exception
|
|
private $trace; // backtrace
|
|
private $previous; // previous exception if nested exception
|
|
|
|
public function __construct($message = null, $code = 0, Exception $previous = null);
|
|
|
|
final private function __clone(); // Inhibits cloning of exceptions.
|
|
|
|
final public function getMessage(); // message of exception
|
|
final public function getCode(); // code of exception
|
|
final public function getFile(); // source filename
|
|
final public function getLine(); // source line
|
|
final public function getTrace(); // an array of the backtrace()
|
|
final public function getPrevious(); // previous exception
|
|
final public function getTraceAsString(); // formatted string of trace
|
|
|
|
// Overrideable
|
|
public function __toString(); // formatted string for display
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
If a class extends the built-in Exception class and re-defines the <link
|
|
linkend="language.oop5.decon">constructor</link>, it is highly recommended
|
|
that it also call <link
|
|
linkend="language.oop5.paamayim-nekudotayim">parent::__construct()</link>
|
|
to ensure all available data has been properly assigned. The <link
|
|
linkend="language.oop5.magic">__toString()</link> method can be overridden
|
|
to provide a custom output when the object is presented as a string.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Exceptions cannot be cloned. Attempting to <link
|
|
linkend="language.oop5.cloning">clone</link> an Exception will result in a
|
|
fatal <constant>E_ERROR</constant> error.
|
|
</para>
|
|
</note>
|
|
<example>
|
|
<title>Extending the Exception class (PHP 5.3.0+)</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
/**
|
|
* Define a custom exception class
|
|
*/
|
|
class MyException extends Exception
|
|
{
|
|
// Redefine the exception so message isn't optional
|
|
public function __construct($message, $code = 0, Exception $previous = null) {
|
|
// some code
|
|
|
|
// make sure everything is assigned properly
|
|
parent::__construct($message, $code, $previous);
|
|
}
|
|
|
|
// custom string representation of object
|
|
public function __toString() {
|
|
return __CLASS__ . ": [{$this->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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Example 1
|
|
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
|
|
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
|
|
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
|
|
try {
|
|
$o = new TestException();
|
|
} catch (Exception $e) { // Skipped, no exception
|
|
echo "Default Exception caught\n", $e;
|
|
}
|
|
|
|
// Continue execution
|
|
var_dump($o); // TestException
|
|
echo "\n\n";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
<note>
|
|
<para>
|
|
Versions of PHP 5, prior to PHP 5.3.0 do not support nesting of exceptions.
|
|
The following code fragment can be used as a replacement MyException class
|
|
if you wish to run this example.
|
|
</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
/**
|
|
* Define a custom exception class
|
|
*/
|
|
class MyException extends Exception
|
|
{
|
|
// Redefine the exception so message isn't optional
|
|
public function __construct($message, $code = 0) {
|
|
// some code
|
|
|
|
// make sure everything is assigned properly
|
|
parent::__construct($message, $code);
|
|
}
|
|
|
|
// custom string representation of object
|
|
public function __toString() {
|
|
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
|
|
}
|
|
|
|
public function customFunction() {
|
|
echo "A custom function for this type of exception\n";
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</note>
|
|
</example>
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|