5. E_ERROR
• 產生以下錯誤
Fatal error: Uncaught Error: Call to undefined function bar() in
D:wwwslimpublicindex.php:7
• 因為 function 根本不存在,系統無從猜測可能的行為,也無法修復錯誤,故為
Fatal Error,強制停止程式運作。
function foo() {
echo 'foo';
}
bar(); // 呼叫了不存在的 function
6. E_WARNING
• 產生以下錯誤畫面:
Warning: A non-numeric value encountered in D:wwwslimpublicindex.php on line 3
123
• 不正確的資料操作與計算,可能造成程式 BUG,但是系統可以修復其行為,所以
程式不會中斷,可以被隱藏。
$result = 123 + 'ABC'; // 數字加字串
echo sprintf('<span style="color: red;">%s</span>', $result);
7. E_NOTICE
• 產生以下畫面
Notice: Undefined variable: b in D:wwwslimpublicindex.php on line 6
A
• $b 沒有被預先宣告,這種寫法在 PHP 中是允許的,但是這樣子有很大機率出現
BUG ,故 PHP 會用 Notice 提示你最好預先宣告。
$a = 'A';
$ab = $a . $b; // $b 不存在
echo $ab;
8. E_STRICT
• 產生以下錯誤訊息
Warning: Declaration of B::foo() should be compatible with A::foo($a = 123)
in D:wwwslimpublicindex.php on line 17
對PHP開發過程更嚴謹的要求。
class A {
public function foo($a = 123)
{
}
}
class B extends A
{
// 與 parent class 介面不一樣
public function foo()
{
}
}
9. E_DEPRECATED
• 產生以下畫面
Deprecated: Function mcrypt_create_iv() is deprecated
in D:wwwslimpublicindex.php on line 6
�Ի��eD��IN�
• 若使用了已被棄用的語言功能就會發出此提示,提醒你趕快改用新功能。
error_reporting(E_ALL);
// PHP 7.2 deprecated mcrypt
$v = mcrypt_create_iv(16);
echo $v;
10. 你也可以產生屬於自己的錯誤訊息
• 用 trigger_error() 來立即觸發使用者定義的錯誤訊息
• 預設值是 E_USER_NOTICE,所以程式會繼續執行下去,只是跳 Notice 訊息。
Notice: $a is not A in D:wwwslimpublicindex.php on line 6
B
$a = 'B';
if ($a !== 'A') {
trigger_error('$a is not A', E_USER_NOTICE);
}
echo $a;
11. 改用 E_USER_ERROR
• 這次用的是 ERROR type,程式就會終止執行了:
Fatal error: $a is not A in D:wwwslimpublicindex.php on line 6
• 可用的種類有:
E_USER_ERROR, E_USER_NOTICE, E_USER_WARNING, E_USER_DEPRECATED 等
大多數 E_* 的錯誤訊息,都有 E_USER_* 的對應
if ($a !== 'A') {
trigger_error('$a is not A', E_USER_ERROR);
}
35. Exception 可以無視層次跳躍
• 範例中 Exception 是在 function 內拋出,但是外部的 try ... catch 可以抓到。
• Exception 是無視層次的,會向上一直跳到有 try ... catch 的地方才停止。
• 如果沒有 try ... catch,則會跳到最上層,成為 Fatal Error 終止程序。
function foo($a) {
if ($a !== 'A') {
throw new RuntimeException('$a is not A');
}
echo $a;
}
try {
foo('B');
} catch (RuntimeException $e) {
echo $e->getMessage();
}
36. 沒有捕獲 Exception 的結果
• 會顯示 Uncaught Exception 然後終止程序
Fatal error: Uncaught RuntimeException: $a is not A in D:wwwslimpublicindex.php:5
Stack trace: #0 D:wwwslimpublicindex.php(11): foo('B') #1 {main} thrown
in D:wwwslimpublicindex.php on line 5
function foo($a) {
if ($a !== 'A') {
throw new RuntimeException('$a is not A');
}
echo $a;
}
foo('B');
46. 不要這樣用
• 如果你只是想讓未登入 user 轉過去登入頁面,在這個案例中,用 if 就能處理了
try {
if ($user->group === 'guest') {
throw new UnauthorisedException('Please login', 401);
} elseif (...) {
} elseif (...) {
} else {
}
} catch (UnauthorisedException $e) {
header('Location: /login');
}
if ($user->group === 'guest') {
header('Location: /login');
}
47. 但可以這樣用
• 這個案例中,user group 如果出現預定義的格式以外的值,肯定屬於異常狀況,就
直接拋出 Exception 吧。
switch ($user->group) {
case 'guest':
// Please login first.
case 'member':
// Welcome Back
case 'manager':
// Sir, yes sir.
default:
throw new UnauthorisedException('Uh... Who are you?', 403);
}
50. 使用 Exception 的情境
• 通常比較少在同一個空間內同時 try ... catch 又同時 throw Exception。
• 開發 function 的人可以根據異常狀況拋出各種 Exception,幫助使用 function 的人
處理例外流程。
• 使用 function 的人可以用 try ... catch 捕獲 function 的異常,然後處理可能的錯誤
修復。
• 是否是【異常】非常重要,既定的可預期流程,都應該用 if else 處理。但是異常
的處理可以放心用 Exception 作流程跳轉。
51. 防禦型程式設計
public function __construct($string, $int, $array)
{
// 最基本的檢查,型別不對就丟錯
if (!is_string($string))
{
throw new InvalidArgumentException('Argument 1 should be string.');
}
// 這個檢查比較鬆一點,只要是數字都可以過,不一定要 int 型態
if (!is_numeric($int))
{
throw new InvalidArgumentException('Argument 2 should be a number.');
}
// 這個檢查比較特別,如果是 Iterator 物件也能夠接受,因為同樣可以 foreach
if (!is_array($array) && !($array instanceof Traversable))
{
throw new InvalidArgumentException('Argument 3 should be Traversable.');
}
// Do some stuff
}