<?xml version="1.0" encoding="iso-8859-1"?> <!-- $Revision: 1.10 $ --> <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 exeptions. 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> <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 built-in exceptions. </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>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 protected $code = 0; // user defined exception code protected $file; // source filename of exception protected $line; // source line of exception function __construct($message = null, $code = 0); final function getMessage(); // message of exception final function getCode(); // code of exception final function getFile(); // source filename final function getLine(); // source line final function getTrace(); // an array of the backtrace() final function getTraceAsString(); // formatted string of trace /* Overrideable */ 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> <example> <title>Extending the Exception class</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) { // 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"; } } /** * 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); 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); 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); 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); echo "\n\n"; ?> ]]> </programlisting> </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:"../../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 -->