php-doc-en/language/exceptions.xml
Adam Harvey 8ad0d94e1c Add initial migration guide for PHP 5.5.
What's done: the migration guide itself, updates to existing functions and
functionality, and new language features.

What's not done: stub pages for new functions and methods. (I'd rather get this
in now, though, than have it languish on my hard drive any longer so that other
people can contribute.)

What could use help: the generator chapter is pretty rough and ready. Better
examples would be awesome. I certainly won't argue if somebody wants to add the
function stubs, either.


git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@328430 c90b9560-bf6c-de11-be94-00142212c4b1
2012-11-20 15:17:23 +00:00

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 catch
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.');
}
else 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';
?>
]]>
</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.');
}
else 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';
?>
]]>
</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
-->