language/exceptions.xml
7a75b854c8c52226d38397e7e8177e339fdb273f
...
...
@@ -1,244 +1,47 @@
1
1
<?xml version="1.0" encoding="utf-8"?>
2
2
<!-- $Revision$ -->
3
-
<chapter xml:id="language.exceptions" xmlns="http://docbook.org/ns/docbook">
4
-
<title>Exceptions</title>
5
-
6
-
<sect1 xml:id="language.exceptions.extending">
7
-
<title>Extending Exceptions</title>
8
-
<para>
9
-
A User defined Exception class can be defined by extending the built-in
10
-
Exception class. The members and properties below, show what is accessible
11
-
within the child class that derives from the built-in Exception class.
12
-
</para>
13
-
<example>
14
-
<title>The Built in Exception class</title>
15
-
<programlisting role="php">
16
-
<![CDATA[
17
-
<?php
18
-
class Exception
19
-
{
20
-
protected $message = 'Unknown exception'; // exception message
21
-
private $string; // __toString cache
22
-
protected $code = 0; // user defined exception code
23
-
protected $file; // source filename of exception
24
-
protected $line; // source line of exception
25
-
private $trace; // backtrace
26
-
private $previous; // previous exception if nested exception
27
-

28
-
public function __construct($message = null, $code = 0, Exception $previous = null);
29
-

30
-
final private function __clone(); // Inhibits cloning of exceptions.
31
-

32
-
final public function getMessage(); // message of exception
33
-
final public function getCode(); // code of exception
34
-
final public function getFile(); // source filename
35
-
final public function getLine(); // source line
36
-
final public function getTrace(); // an array of the backtrace()
37
-
final public function getPrevious(); // previous exception
38
-
final public function getTraceAsString(); // formatted string of trace
39
-

40
-
// Overrideable
41
-
public function __toString(); // formatted string for display
42
-
}
43
-
?>
44
-
]]>
45
-
</programlisting>
46
-
</example>
47
-
<para>
48
-
If a class extends the built-in Exception class and re-defines the <link
49
-
linkend="language.oop5.decon">constructor</link>, it is highly recommended
50
-
that it also call <link
51
-
linkend="language.oop5.paamayim-nekudotayim">parent::__construct()</link>
52
-
to ensure all available data has been properly assigned. The <link
53
-
linkend="language.oop5.magic">__toString()</link> method can be overridden
54
-
to provide a custom output when the object is presented as a string.
55
-
</para>
56
-
<note>
57
-
<para>
58
-
Exceptions cannot be cloned. Attempting to <link
59
-
linkend="language.oop5.cloning">clone</link> an Exception will result in a
60
-
fatal <constant>E_ERROR</constant> error.
61
-
</para>
62
-
</note>
63
-
<example>
64
-
<title>Extending the Exception class (PHP 5.3.0+)</title>
65
-
<programlisting role="php">
66
-
<![CDATA[
67
-
<?php
68
-
/**
69
-
* Define a custom exception class
70
-
*/
71
-
class MyException extends Exception
72
-
{
73
-
// Redefine the exception so message isn't optional
74
-
public function __construct($message, $code = 0, Exception $previous = null) {
75
-
// some code
76
-
77
-
// make sure everything is assigned properly
78
-
parent::__construct($message, $code, $previous);
79
-
}
80
-

81
-
// custom string representation of object
82
-
public function __toString() {
83
-
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
84
-
}
85
-

86
-
public function customFunction() {
87
-
echo "A custom function for this type of exception\n";
88
-
}
89
-
}
90
-

91
-

92
-
/**
93
-
* Create a class to test the exception
94
-
*/
95
-
class TestException
96
-
{
97
-
public $var;
98
-

99
-
const THROW_NONE = 0;
100
-
const THROW_CUSTOM = 1;
101
-
const THROW_DEFAULT = 2;
102
-

103
-
function __construct($avalue = self::THROW_NONE) {
104
-

105
-
switch ($avalue) {
106
-
case self::THROW_CUSTOM:
107
-
// throw custom exception
108
-
throw new MyException('1 is an invalid parameter', 5);
109
-
break;
110
-

111
-
case self::THROW_DEFAULT:
112
-
// throw default one.
113
-
throw new Exception('2 is not allowed as a parameter', 6);
114
-
break;
115
-

116
-
default:
117
-
// No exception, object will be created.
118
-
$this->var = $avalue;
119
-
break;
120
-
}
121
-
}
122
-
}
123
-

124
-

125
-
// Example 1
126
-
try {
127
-
$o = new TestException(TestException::THROW_CUSTOM);
128
-
} catch (MyException $e) { // Will be caught
129
-
echo "Caught my exception\n", $e;
130
-
$e->customFunction();
131
-
} catch (Exception $e) { // Skipped
132
-
echo "Caught Default Exception\n", $e;
133
-
}
134
-

135
-
// Continue execution
136
-
var_dump($o); // Null
137
-
echo "\n\n";
138
-

139
-

140
-
// Example 2
141
-
try {
142
-
$o = new TestException(TestException::THROW_DEFAULT);
143
-
} catch (MyException $e) { // Doesn't match this type
144
-
echo "Caught my exception\n", $e;
145
-
$e->customFunction();
146
-
} catch (Exception $e) { // Will be caught
147
-
echo "Caught Default Exception\n", $e;
148
-
}
149
-

150
-
// Continue execution
151
-
var_dump($o); // Null
152
-
echo "\n\n";
153
-

154
-

155
-
// Example 3
156
-
try {
157
-
$o = new TestException(TestException::THROW_CUSTOM);
158
-
} catch (Exception $e) { // Will be caught
159
-
echo "Default Exception caught\n", $e;
160
-
}
161
-

162
-
// Continue execution
163
-
var_dump($o); // Null
164
-
echo "\n\n";
165
-

166
-

167
-
// Example 4
168
-
try {
169
-
$o = new TestException();
170
-
} catch (Exception $e) { // Skipped, no exception
171
-
echo "Default Exception caught\n", $e;
172
-
}
173
-

174
-
// Continue execution
175
-
var_dump($o); // TestException
176
-
echo "\n\n";
177
-
?>
178
-
]]>
179
-
</programlisting>
180
-
<note>
181
-
<para>
182
-
Versions of PHP 5, prior to PHP 5.3.0 do not support nesting of exceptions.
183
-
The following code fragment can be used as a replacement MyException class
184
-
if you wish to run this example.
185
-
</para>
186
-
<programlisting role="php">
187
-
<![CDATA[
188
-
<?php
189
-
/**
190
-
* Define a custom exception class
191
-
*/
192
-
class MyException extends Exception
193
-
{
194
-
// Redefine the exception so message isn't optional
195
-
public function __construct($message, $code = 0) {
196
-
// some code
197
-
198
-
// make sure everything is assigned properly
199
-
parent::__construct($message, $code);
200
-
}
201
-

202
-
// custom string representation of object
203
-
public function __toString() {
204
-
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
205
-
}
206
-

207
-
public function customFunction() {
208
-
echo "A custom function for this type of exception\n";
209
-
}
210
-
}
211
-
?>
212
-
]]>
213
-
</programlisting>
214
-
</note>
215
-
</example>
216
-
</sect1>
217
-

218
-
<simplesect xml:id="language.exceptions.introduction">
3
+
<chapter xml:id="language.exceptions" xmlns="http://docbook.org/ns/docbook">
4
+
<title>Exceptions</title>
5
+
<para>
6
+
PHP has an exception model similar to that of other programming
7
+
languages. An exception can be &throw;n, and caught ("&catch;ed") within
8
+
PHP. Code may be surrounded in a &try; block, to facilitate the catching
9
+
of potential exceptions. Each &try; must have at least one corresponding
10
+
&catch; or &finally; block.
11
+
</para>
12
+
<para>
13
+
If an exception is thrown and its current function scope has no &catch;
14
+
block, the exception will "bubble up" the call stack to the calling
15
+
function until it finds a matching &catch; block. All &finally; blocks it encounters
16
+
along the way will be executed. If the call stack is unwound all the way to the
17
+
global scope without encountering a matching &catch; block, the program will
18
+
terminate with a fatal error unless a global exception handler has been set.
19
+
</para>
20
+
<para>
21
+
The thrown object must be an &instanceof; <interfacename>Throwable</interfacename>.
22
+
Trying to throw an object that is not will result in a PHP Fatal Error.
23
+
</para>
24
+
<para>
25
+
As of PHP 8.0.0, the &throw; keyword is an expression and may be used in any expression
26
+
context. In prior versions it was a statement and was required to be on its own line.
27
+
</para>
28
+

29
+
<sect1 annotations="chunk:false" xml:id="language.exceptions.catch">
30
+
<title><literal>catch</literal></title>
219
31
<para>
220
-
PHP 5 has an exception model similar to that of other programming
221
-
languages. An exception can be &throw;n, and caught ("&catch;ed") within
222
-
PHP. Code may be surrounded in a &try; block, to facilitate the catching
223
-
of potential exceptions. Each &try; must have at least one corresponding
224
-
&catch; or &finally; block.
32
+
A &catch; block defines how to respond to a thrown exception. A &catch;
33
+
block defines one or more types of exception or error it can handle, and
34
+
optionally a variable to which to assign the exception. (The variable was
35
+
required prior to PHP 8.0.0.) The first &catch; block a thrown exception
36
+
or error encounters that matches the type of the thrown object will handle
37
+
the object.
225
38
</para>
226
-

227
-
<para>
228
-
The thrown object must be an instance of the
229
-
<classname>Exception</classname> class or a subclass of
230
-
<classname>Exception</classname>. Trying to throw an object that is not
231
-
will result in a PHP Fatal Error.
232
-
</para>
233
-
</simplesect>
234
-

235
-
<simplesect xml:id="language.exceptions.catch">
236
-
<title><literal>catch</literal></title>
237
39
<para>
238
40
Multiple &catch; blocks can be used to catch different classes of
239
41
exceptions. Normal execution (when no exception is thrown within the &try;
240
42
block) will continue after that last &catch; block defined in sequence.
241
-
Exceptions can be &throw;n (or re-thrown) within a &catch; block.
43
+
Exceptions can be &throw;n (or re-thrown) within a &catch; block. If not,
44
+
execution will continue after the &catch; block that was triggered.
242
45
</para>
243
46
<para>
244
47
When an exception is thrown, code following the statement will not be
...
...
@@ -247,29 +50,74 @@ class MyException extends Exception
247
50
"<literal>Uncaught Exception ...</literal>" message, unless a handler has
248
51
been defined with <function>set_exception_handler</function>.
249
52
</para>
250
-
</simplesect>
53
+
<para>
54
+
As of PHP 7.1.0, a &catch; block may specify multiple exceptions
55
+
using the pipe (<literal>|</literal>) character. This is useful for when
56
+
different exceptions from different class hierarchies are handled the
57
+
same.
58
+
</para>
59
+
<para>
60
+
As of PHP 8.0.0, the variable name for a caught exception is optional.
61
+
If not specified, the &catch; block will still execute but will not
62
+
have access to the thrown object.
63
+
</para>
64
+
</sect1>
251
65

252
-
<simplesect xml:id="language.exceptions.finally">
66
+
<sect1 annotations="chunk:false" xml:id="language.exceptions.finally">
253
67
<title><literal>finally</literal></title>
254
68
<para>
255
-
In PHP 5.5 and later, a &finally; block may also be specified after or
69
+
A &finally; block may also be specified after or
256
70
instead of &catch; blocks. Code within the &finally; block will always be
257
71
executed after the &try; and &catch; blocks, regardless of whether an
258
72
exception has been thrown, and before normal execution resumes.
259
73
</para>
260
-
</simplesect>
74
+
<para>
75
+
One notable interaction is between the &finally; block and a &return; statement.
76
+
If a &return; statement is encountered inside either the &try; or the &catch; blocks,
77
+
the &finally; block will still be executed. Moreover, the &return; statement is
78
+
evaluated when encountered, but the result will be returned after the &finally; block
79
+
is executed. Additionally, if the &finally; block also contains a &return; statement,
80
+
the value from the &finally; block is returned.
81
+
</para>
82
+
</sect1>
261
83

262
-
<simplesect xml:id="language.exceptions.notes">
84
+
<sect1 annotations="chunk:false" xml:id="language.exceptions.exception-handler">
85
+
<title>Global exception handler</title>
86
+
<para>
87
+
If an exception is allowed to bubble up to the global scope, it may be caught
88
+
by a global exception handler if set. The <function>set_exception_handler</function>
89
+
function can set a function that will be called in place of a &catch; block if no
90
+
other block is invoked. The effect is essentially the same as if the entire program
91
+
were wrapped in a &try;-&catch; block with that function as the &catch;.
92
+
</para>
93
+
</sect1>
94
+

95
+
<sect1 annotations="chunk:false" xml:id="language.exceptions.notes">
263
96
&reftitle.notes;
264
97

265
98
<note>
266
99
<para>
267
100
Internal PHP functions mainly use
268
101
<link linkend="ini.error-reporting">Error reporting</link>, only modern
269
-
<link linkend="language.oop5">Object oriented</link>
270
-
extensions use exceptions. However, errors can be simply translated to
102
+
<link linkend="language.oop5">Object-oriented</link>
103
+
extensions use exceptions. However, errors can be easily translated to
271
104
exceptions with <link linkend="class.errorexception">ErrorException</link>.
105
+
This technique only works with non-fatal errors, however.
272
106
</para>
107
+
<example>
108
+
<title>Converting error reporting to exceptions</title>
109
+
<programlisting role="php">
110
+
<![CDATA[
111
+
<?php
112
+
function exceptions_error_handler($severity, $message, $filename, $lineno) {
113
+
throw new ErrorException($message, 0, $severity, $filename, $lineno);
114
+
}
115
+

116
+
set_error_handler('exceptions_error_handler');
117
+
?>
118
+
]]>
119
+
</programlisting>
120
+
</example>
273
121
</note>
274
122
<tip>
275
123
<para>
...
...
@@ -278,9 +126,9 @@ class MyException extends Exception
278
126
exceptions</link>.
279
127
</para>
280
128
</tip>
281
-
</simplesect>
129
+
</sect1>
282
130

283
-
<simplesect xml:id="language.exceptions.examples">
131
+
<sect1 annotations="chunk:false" xml:id="language.exceptions.examples">
284
132
&reftitle.examples;
285
133

286
134
<example>
...
...
@@ -317,7 +165,7 @@ Hello World
317
165
</screen>
318
166
</example>
319
167
<example>
320
-
<title>Exception handling with a <literal>finally</literal> block</title>
168
+
<title>Exception handling with a &finally; block</title>
321
169
<programlisting role="php">
322
170
<![CDATA[
323
171
<?php
...
...
@@ -361,6 +209,33 @@ Hello World
361
209
</screen>
362
210
</example>
363
211
<example>
212
+
<title>Interaction between the &finally; block and &return;</title>
213
+
<programlisting role="php">
214
+
<![CDATA[
215
+
<?php
216
+

217
+
function test() {
218
+
try {
219
+
throw new Exception('foo');
220
+
} catch (Exception $e) {
221
+
return 'catch';
222
+
} finally {
223
+
return 'finally';
224
+
}
225
+
}
226
+

227
+
echo test();
228
+
?>
229
+
]]>
230
+
</programlisting>
231
+
&example.outputs;
232
+
<screen>
233
+
<![CDATA[
234
+
finally
235
+
]]>
236
+
</screen>
237
+
</example>
238
+
<example>
364
239
<title>Nested Exception</title>
365
240
<programlisting role="php">
366
241
<![CDATA[
...
...
@@ -396,7 +271,259 @@ string(4) "foo!"
396
271
]]>
397
272
</screen>
398
273
</example>
399
-
</simplesect>
274
+
<example>
275
+
<title>Multi catch exception handling</title>
276
+
<programlisting role="php">
277
+
<![CDATA[
278
+
<?php
279
+

280
+
class MyException extends Exception { }
281
+

282
+
class MyOtherException extends Exception { }
283
+

284
+
class Test {
285
+
public function testing() {
286
+
try {
287
+
throw new MyException();
288
+
} catch (MyException | MyOtherException $e) {
289
+
var_dump(get_class($e));
290
+
}
291
+
}
292
+
}
293
+

294
+
$foo = new Test;
295
+
$foo->testing();
296
+

297
+
?>
298
+
]]>
299
+
</programlisting>
300
+
&example.outputs;
301
+
<screen>
302
+
<![CDATA[
303
+
string(11) "MyException"
304
+
]]>
305
+
</screen>
306
+
</example>
307
+
<example>
308
+
<title>Omitting the caught variable</title>
309
+
<para>Only permitted in PHP 8.0.0 and later.</para>
310
+
<programlisting role="php">
311
+
<![CDATA[
312
+
<?php
313
+

314
+
class SpecificException extends Exception {}
315
+

316
+
function test() {
317
+
throw new SpecificException('Oopsie');
318
+
}
319
+

320
+
try {
321
+
test();
322
+
} catch (SpecificException) {
323
+
print "A SpecificException was thrown, but we don't care about the details.";
324
+
}
325
+
?>
326
+
]]>
327
+
</programlisting>
328
+
</example>
329
+
<example>
330
+
<title>Throw as an expression</title>
331
+
<para>Only permitted in PHP 8.0.0 and later.</para>
332
+
<programlisting role="php">
333
+
<![CDATA[
334
+
<?php
335
+

336
+
function test() {
337
+
do_something_risky() or throw new Exception('It did not work');
338
+
}
339
+

340
+
try {
341
+
test();
342
+
} catch (Exception $e) {
343
+
print $e->getMessage();
344
+
}
345
+
?>
346
+
]]>
347
+
</programlisting>
348
+
</example>
349
+
</sect1>
350
+

351
+
<sect1 xml:id="language.exceptions.extending">
352
+
<title>Extending Exceptions</title>
353
+
<para>
354
+
A User defined Exception class can be defined by extending the built-in
355
+
Exception class. The members and properties below, show what is accessible
356
+
within the child class that derives from the built-in Exception class.
357
+
</para>
358
+
<example>
359
+
<title>The Built in Exception class</title>
360
+
<programlisting role="php">
361
+
<![CDATA[
362
+
<?php
363
+
class Exception implements Throwable
364
+
{
365
+
protected $message = 'Unknown exception'; // exception message
366
+
private $string; // __toString cache
367
+
protected $code = 0; // user defined exception code
368
+
protected $file; // source filename of exception
369
+
protected $line; // source line of exception
370
+
private $trace; // backtrace
371
+
private $previous; // previous exception if nested exception
372
+

373
+
public function __construct($message = '', $code = 0, Throwable $previous = null);
374
+

375
+
final private function __clone(); // Inhibits cloning of exceptions.
376
+

377
+
final public function getMessage(); // message of exception
378
+
final public function getCode(); // code of exception
379
+
final public function getFile(); // source filename
380
+
final public function getLine(); // source line
381
+
final public function getTrace(); // an array of the backtrace()
382
+
final public function getPrevious(); // previous exception
383
+
final public function getTraceAsString(); // formatted string of trace
384
+

385
+
// Overrideable
386
+
public function __toString(); // formatted string for display
387
+
}
388
+
?>
389
+
]]>
390
+
</programlisting>
391
+
</example>
392
+
<para>
393
+
If a class extends the built-in Exception class and re-defines the <link
394
+
linkend="language.oop5.decon">constructor</link>, it is highly recommended
395
+
that it also call <link
396
+
linkend="language.oop5.paamayim-nekudotayim">parent::__construct()</link>
397
+
to ensure all available data has been properly assigned. The <link
398
+
linkend="language.oop5.magic">__toString()</link> method can be overridden
399
+
to provide a custom output when the object is presented as a string.
400
+
</para>
401
+
<note>
402
+
<para>
403
+
Exceptions cannot be cloned. Attempting to <link
404
+
linkend="language.oop5.cloning">clone</link> an Exception will result in a
405
+
fatal <constant>E_ERROR</constant> error.
406
+
</para>
407
+
</note>
408
+
<example>
409
+
<title>Extending the Exception class</title>
410
+
<programlisting role="php">
411
+
<![CDATA[
412
+
<?php
413
+
/**
414
+
* Define a custom exception class
415
+
*/
416
+
class MyException extends Exception
417
+
{
418
+
// Redefine the exception so message isn't optional
419
+
public function __construct($message, $code = 0, Throwable $previous = null) {
420
+
// some code
421
+

422
+
// make sure everything is assigned properly
423
+
parent::__construct($message, $code, $previous);
424
+
}
425
+

426
+
// custom string representation of object
427
+
public function __toString() {
428
+
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
429
+
}
430
+

431
+
public function customFunction() {
432
+
echo "A custom function for this type of exception\n";
433
+
}
434
+
}
435
+

436
+

437
+
/**
438
+
* Create a class to test the exception
439
+
*/
440
+
class TestException
441
+
{
442
+
public $var;
443
+

444
+
const THROW_NONE = 0;
445
+
const THROW_CUSTOM = 1;
446
+
const THROW_DEFAULT = 2;
447
+

448
+
function __construct($avalue = self::THROW_NONE) {
449
+

450
+
switch ($avalue) {
451
+
case self::THROW_CUSTOM:
452
+
// throw custom exception
453
+
throw new MyException('1 is an invalid parameter', 5);
454
+
break;
455
+

456
+
case self::THROW_DEFAULT:
457
+
// throw default one.
458
+
throw new Exception('2 is not allowed as a parameter', 6);
459
+
break;
460
+

461
+
default:
462
+
// No exception, object will be created.
463
+
$this->var = $avalue;
464
+
break;
465
+
}
466
+
}
467
+
}
468
+

469
+

470
+
// Example 1
471
+
try {
472
+
$o = new TestException(TestException::THROW_CUSTOM);
473
+
} catch (MyException $e) { // Will be caught
474
+
echo "Caught my exception\n", $e;
475
+
$e->customFunction();
476
+
} catch (Exception $e) { // Skipped
477
+
echo "Caught Default Exception\n", $e;
478
+
}
479
+

480
+
// Continue execution
481
+
var_dump($o); // Null
482
+
echo "\n\n";
483
+

484
+

485
+
// Example 2
486
+
try {
487
+
$o = new TestException(TestException::THROW_DEFAULT);
488
+
} catch (MyException $e) { // Doesn't match this type
489
+
echo "Caught my exception\n", $e;
490
+
$e->customFunction();
491
+
} catch (Exception $e) { // Will be caught
492
+
echo "Caught Default Exception\n", $e;
493
+
}
494
+

495
+
// Continue execution
496
+
var_dump($o); // Null
497
+
echo "\n\n";
498
+

499
+

500
+
// Example 3
501
+
try {
502
+
$o = new TestException(TestException::THROW_CUSTOM);
503
+
} catch (Exception $e) { // Will be caught
504
+
echo "Default Exception caught\n", $e;
505
+
}
506
+

507
+
// Continue execution
508
+
var_dump($o); // Null
509
+
echo "\n\n";
510
+

511
+

512
+
// Example 4
513
+
try {
514
+
$o = new TestException();
515
+
} catch (Exception $e) { // Skipped, no exception
516
+
echo "Default Exception caught\n", $e;
517
+
}
518
+

519
+
// Continue execution
520
+
var_dump($o); // TestException
521
+
echo "\n\n";
522
+
?>
523
+
]]>
524
+
</programlisting>
525
+
</example>
526
+
</sect1>
400
527

401
528
</chapter>
402
529
403
530