PHP 예외 처리
예외(Exception)는 지정된 오류가 발생할 때 스크립트의 정상적인 흐름을 변경하는 데 사용됩니다.
예외는 무엇인가요?
PHP 5는 새로운 객체 지향적 오류 처리 방법을 제공합니다.
예외 처리는 지정된 오류(예외)가 발생할 때 스크립트의 정상적인 흐름을 변경하는 데 사용됩니다. 이 상황을 예외라고 합니다.
예외가 발생할 때, 일반적으로 다음과 같이 발생합니다:
- 현재 코드 상태가 저장됩니다
- 코드 실행이 예약된 예외 처리기 함수로 전환됩니다
- 상황에 따라 처리기는 저장된 코드 상태에서 코드를 다시 시작하거나 스크립트 실행을 종료하거나 코드의 다른 위치에서 스크립트를 계속 실행할 수 있습니다.
다양한 오류 처리 방법을 보여드리겠습니다:
- 예외의 기본 사용
- 사용자 정의 예외 처리기 생성
- 여러 예외
- 재발생 예외
- 최상위 예외 처리기 설정
예외의 기본 사용
예외가 투げ뜨려지면, 그 이후의 코드는 계속 실행되지 않으며 PHP는 일치하는 "catch" 코드 블록을 찾으려고 시도합니다.
예외가 잡히지 않았고 set_exception_handler()를 사용하여 적절한 처리를 하지 않았다면, 심각한 오류(최종 오류)가 발생하고 "Uncaught Exception" (미취소된 예외) 오류 메시지가 출력됩니다.
다음과 같이 예외를 투げ던지고 동시에 그를 잡지 않으려고 시도해 보겠습니다:
<?php //exception throwing function 생성 function checkNum($number) { if($number>1) { throw new Exception("값은 1 또는 그 이하여야 합니다"); } return true; } //exception trigger checkNum(2); ?>
위의 코드는 다음과 같은 오류를 얻습니다:
최종 오류: 미취소된 예외 'Exception' message 'Value must be 1 or below' in C:\webfolder\test.php:6 스택 트레이스: #0 C:\webfolder\test.php(12): checkNum(28) #1 {main} thrown in C:\webfolder\test.php on line 6
Try, throw 및 catch
위의 예제에서 발생하는 오류를 피하기 위해, 예외를 처리하는 적절한 코드를 생성해야 합니다.
정확한 처리 프로그램은 다음과 같아야 합니다:
- Try - 예외를 일으키는 함수는 "try" 코드 블록 내에 위치해야 합니다. 예외가 발생하지 않으면 코드가 일반적으로 계속 실행됩니다. 하지만 예외가 발생하면 예외가 투げ뜨려집니다.
- Throw - 여기서는 예외를 투げném하는 방법을 정의합니다. 각 "throw"은 최소한 하나의 "catch"와 일치해야 합니다
- Catch - "catch" 코드 블록은 예외를 잡고, 예외 정보를 포함한 객체를 생성합니다
그럼 예외를 투げném해 보겠습니다:
<?php // 예외를 투げném할 수 있는 함수를 생성합니다 function checkNum($number) { if($number>1) { throw new Exception("값은 1 또는 그 이하여야 합니다"); } return true; } // "try" 코드 블록에서 예외를 투げném합니다 try { checkNum(2); // 예외가 투げném되면, 이 텍스트는 표시되지 않습니다 echo '이를 볼 수 있다면, 숫자는 1 또는 그 이하입니다'; } // 예외를 잡기 catch(Exception $e) { echo 'Message: ' .$e->getMessage(); } ?>
위 코드는 이와 같은 오류를 얻습니다:
Message: 값은 1 또는 그 이하여야 합니다
例子解释:
위 코드는 예외를 투げném하고, 그것을 잡습니다:
- checkNum() 함수를 생성합니다. 이 함수는 숫자가 1보다 크면 예외를 투げ뜁니다.
- "try" 코드 블록에서 checkNum() 함수를 호출합니다.
- checkNum() 함수에서 예외가 발생합니다
- "catch" 코드 블록이 이 예외를 받아들이고, 예외 정보를 포함한 객체 ($e)를 생성합니다.
- exception 객체에서 $e->getMessage()을 호출하여 이 예외의 오류 메시지를 출력합니다
그러나 “각 throw은 catch와 일치해야 한다”는 원칙을 따르기 위해, 누락된 오류를 처리하기 위해 최상위 예외 처리기를 설정할 수 있습니다.
사용자 정의 Exception 클래스를 생성하십시오
사용자 정의 예외 처리기를 생성하는 것은 매우 간단합니다. PHP에서 예외가 발생할 때 호출할 수 있는 특별한 클래스를 간단히 생성합니다. 이 클래스는 exception 클래스의 확장이어야 합니다.
이 개별적인 exception 클래스는 PHP의 exception 클래스의 모든 속성을 상속받습니다. 여기서는 사용자 정의 함수를 추가할 수 있습니다.
우리는 exception 클래스를 생성하기 시작합니다:
<?php class customException extends Exception { public function errorMessage() { //error message $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile() ': <b>'.$this->getMessage().'</b>는 유효한 이메일 주소가 아닙니다'; return $errorMsg; } } $email = "someone@example...com"; try { //check if if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //throw exception if email is not valid throw new customException($email); } } catch (customException $e) { //display custom message echo $e->errorMessage(); } ?>
이 새로운 클래스는 오래된 예외 클래스의 복사본으로 errorMessage() 함수가 추가되었습니다. 이 클래스가 복사본이기 때문에, 오래된 클래스에서 상속받은 속성과 메서드를 사용할 수 있습니다. 예를 들어 getLine(), getFile(), getMessage()와 같은 예외 클래스의 메서드를 사용할 수 있습니다.
例子解释:
위 코드는 예외를 던지고, 그 예외를 사용자 정의 예외 클래스로 잡습니다:
- customException() 类是作为旧的 exception 类的一个扩展来创建的。这样它就继承了旧类的所有属性和方法。
- errorMessage() 함수를 생성합니다. 이메일 주소가 불법적이면 이 함수는 오류 메시지를 반환합니다
- $email 변수를 불법적인 이메일 주소 문자열로 설정합니다
- "try" 코드 블록을 실행하면 이메일 주소가 불법적이기 때문에 예외가 발생합니다
- "catch" 코드 블록은 예외를 잡고 오류 메시지를 표시합니다
여러 예외
하나의 스크립트에 여러 예외를 사용하여 여러 가지 상황을 검사할 수 있습니다.
여러 if..else 코드 블록, 또는 하나의 switch 코드 블록, 또는 여러 예외를 중첩하여 사용할 수 있습니다. 이 예외들은 다른 예외 클래스를 사용하여 다른 오류 메시지를 반환할 수 있습니다:
<?php class customException extends Exception { public function errorMessage() { //error message $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile() ': <b>'.$this->getMessage().'</b>는 유효한 이메일 주소가 아닙니다'; return $errorMsg; } } $email = "someone@example.com"; try { //check if if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //throw exception if email is not valid throw new customException($email); } //check for "example" in mail address if(strpos($email, "example") !== FALSE) { throw new Exception("$email is an example e-mail"); } } catch (customException $e) { echo $e->errorMessage(); } catch(Exception $e) { echo $e->getMessage(); } ?>
例子解释:
위 코드는 두 가지 조건을 테스트했으며, 어떤 조건도 성립하지 않으면 예외를 던집니다:
- customException() 类是作为旧的 exception 类的一个扩展来创建的。这样它就继承了旧类的所有属性和方法。
- 创建 errorMessage() 函数。如果 e-mail 地址不合法,则该函数返回一个错误消息。
- "try" 코드 블록을 실행하면 첫 번째 조건에서 예외가 발생하지 않습니다.
- e-mail이 "example" 문자열을 포함하고 있기 때문에 두 번째 조건이 예외를 발생시킵니다.
- "catch" 코드 블록은 예외를 잡고 적절한 오류 메시지를 표시합니다
customException을 잡지 못하고 base exception만 잡았다면, 그곳에서 예외를 처리합니다.
재발생 예외
어떤 경우에도 예외가 발생할 때, 표준 방식과 다른 방식으로 처리하고 싶을 수 있습니다. "catch" 코드 블록에서 예외를 다시 던질 수 있습니다.
스크립트는 사용자에게 시스템 오류를 숨기는 것이 좋습니다. 시스템 오류는 프로그래머에게 중요할 수 있지만, 사용자는 그들에 대해 관심이 없습니다. 사용자가 더 쉽게 사용할 수 있도록, 사용자에게 친화적인 메시지를 포함한 예외를 다시 던질 수 있습니다:
<?php class customException extends Exception { public function errorMessage() { //error message $errorMsg = $this->getMessage().' is not a valid E-Mail address.'; return $errorMsg; } } $email = "someone@example.com"; try { try { //check for "example" in mail address if(strpos($email, "example") !== FALSE) { //throw exception if email is not valid throw new Exception($email); } } catch(Exception $e) { //re-throw exception throw new customException($email); } } catch (customException $e) { //display custom message echo $e->errorMessage(); } ?>
例子解释:
上面的代码检测在邮件地址中是否含有字符串 "example"。如果有,则再次抛出异常:
- customException() 类是作为旧的 exception 类的一个扩展来创建的。这样它就继承了旧类的所有属性和方法。
- 创建 errorMessage() 函数。如果 e-mail 地址不合法,则该函数返回一个错误消息。
- 把 $email 变量设置为一个有效的邮件地址,但含有字符串 "example"。
- "try" 代码块包含另一个 "try" 代码块,这样就可以再次抛出异常。
- 由于 e-mail 包含字符串 "example",因此触发异常。
- "catch" 捕获到该异常,并重新抛出 "customException"。
- 捕获到 "customException",并显示一条错误消息。
현재 "try" 코드 블록에서 예외가 잡히지 않았다면, 더 높은 레벨에서 catch 코드 블록을 찾을 것입니다.
톱 레벨 예외 처리기 설정
set_exception_handler() 함수는 모든 잡히지 않은 예외를 처리하는 사용자 정의 함수를 설정할 수 있습니다.
<?php function myException($exception) { echo "<b>Exception:</b> " , $exception->getMessage(); } set_exception_handler('myException'); throw new Exception('Uncaught Exception occurred'); ?>
위의 코드의 출력은 다음과 같아야 합니다:
Exception: Uncaught Exception occurred
위의 코드에서 "catch" 코드 블록이 없으며, 대신 톱 레벨 예외 처리 프로그램이 트리거됩니다. 모든 잡히지 않은 예외를 잡기 위해 이 함수를 사용해야 합니다.
예외의 규칙
- 예외 처리가 필요한 코드는 잠재적인 예외를 잡기 위해 try 코드 블록 내에 배치되어야 합니다.
- 각각의 try 또는 throw 코드 블록은 적어도 하나의对应的 catch 코드 블록을 가져야 합니다.
- 다양한 종류의 예외를 잡을 수 있는 여러 개의 catch 코드 블록을 사용할 수 있습니다.
- catch 코드 블록 내에서는 다시 예외를 던질 수 있습니다(re-thrown).
간단히 말해서: 예외가 발생하면 반드시 잡아야 합니다.