예외
목차
PHP에는 다른 프로그래밍 언어와 유사한 예외 모델이 있습니다. 예외를 throw해서, PHP 안에서 잡을(catch) 수 있습니다. 잠재적인 예외를 쉽게 포착하기 위해 코드를 try 블록으로 묶을 수 있습니다. 잠재적인 예외를 잡기 위해서 코드를 try 블록으로 감쌀 수 있습니다. 각 try는 최소한 하나의 catch나 finally 블록을 가져야 합니다.
예외가 발생하고 현재 함수 범위에 catch 블록이 없으면 예외는 일치하는 catch 블록을 찾을 때까지 호출 함수에 대한 호출 스택을 "버블업"합니다. 도중에 만나는 모든 finally 블록이 실행됩니다. 호출 스택이 일치하는 catch 블록을 만나지 않고 전역 범위로 풀린 경우 전역 예외 처리기가 설정되지 않은 한 프로그램은 치명적인 오류와 함께 종료됩니다.
throw된 개체는 Exception 클래스의 인스턴스이거나 Exception의 하위 클래스여야 합니다. 그렇지 않은 객체를 던지려고 하면 PHP 치명적인 오류가 발생합니다.
PHP 8.0.0부터 throw 키워드는 표현식이며 모든 표현식 컨텍스트에서 사용할 수 있습니다. 이전 버전에서는 명령문이었고 자체 라인에 있어야 했습니다.
catch
catch
블록은 throw된 예외에 응답하는 방법을 정의합니다. catch
블록은 처리할 수 있는 하나 이상의 예외 또는 오류 유형을 정의하고 선택적으로 예외를 할당할 변수를 정의합니다. (PHP 8.0.0 이전에는 변수가 필요했습니다.) throw된 개체의 유형과 일치하는 throw된 예외 또는 오류가 발생한 첫 번째 catch
블록은 개체를 처리합니다.
여러 catch
블록을 사용하여 다른 클래스의 예외를 catch할 수 있습니다. 정상적인 실행(try
블록 내에서 예외가 throw되지 않은 경우)은 순서대로 정의된 마지막 catch
블록 이후에 계속됩니다. catch
블록 내에서 예외를 throw
(또는 re-throw)할 수 있습니다. 그렇지 않으면 트리거된 catch
블록 이후에 실행이 계속됩니다.
예외가 발생하면 명령문 다음의 코드는 실행되지 않으며 PHP는 일치하는 첫 번째 catch
블록을 찾으려고 시도합니다. 예외가 catch되지 않으면 set_exception_handler()로 핸들러가 정의되지 않은 한 "Uncaught Exception ...
" 메시지와 함께 PHP 치명적인 오류가 발생합니다.
PHP 7.1.0부터 catch
블록은 파이프(|
) 문자를 사용하여 여러 예외를 지정할 수 있습니다. 이것은 다른 클래스 계층의 다른 예외가 동일하게 처리되는 경우에 유용합니다.
PHP 8.0.0부터 catch
된 예외에 대한 변수 이름은 선택 사항입니다. 지정하지 않으면 catch
블록이 계속 실행되지만 throw된 개체에 액세스할 수 없습니다.
finally
finally
블록은 catch
블록 뒤나 대신 지정할 수도 있습니다. finally
블록 내의 코드는 예외가 발생했는지 여부와 관계없이 try
및 catch
블록 이후와 정상 실행이 재개되기 전에 항상 실행됩니다.
한 가지 주목할만한 상호 작용은 finally
블록과 return
문 사이입니다. try
또는 catch
블록 내에서 return
문이 발생하면 finally
블록이 계속 실행됩니다. 또한 return
문은 만났을 때 평가되지만 finally
블록이 실행된 후에 결과가 반환됩니다. 또한 finally
블록에 return
문이 포함되어 있으면 finally
블록의 값이 반환됩니다.
Global exception handler
예외가 전역 범위까지 버블링되도록 허용된 경우 설정된 경우 전역 예외 처리기에 의해 catch될 수 있습니다. set_exception_handler() 함수는 다른 블록이 호출되지 않으면 catch
블록 대신 호출될 함수를 설정할 수 있습니다. 효과는 본질적으로 전체 프로그램이 해당 함수를 catch
로 사용하여 try
-catchcatch
블록에 래핑된 것과 같습니다.
주의
메모:
내부 PHP 함수는 주로 오류 보고를 사용하며 최신 객체 지향 확장만 예외를 사용합니다. 그러나 오류는 ErrorException을 사용하여 예외로 쉽게 변환될 수 있습니다. 그러나 이 기술은 치명적이지 않은 오류에서만 작동합니다.
예제 #3 오류 보고를 예외로 변환
<?php
function exceptions_error_handler($severity, $message, $filename, $lineno) {
throw new ErrorException($message, 0, $severity, $filename, $lineno);
}
set_error_handler('exceptions_error_handler');
?>
팁 표준 PHP 라이브러리(SPL)는 많은 내장 예외를 제공합니다.
Examples
예제 #4 예외 던지기
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division by zero.');
}
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\n";
?>
위의 예는 다음을 출력합니다.
0.2
Caught exception: Division by zero.
Hello World
예제 #5 finally
블록을 사용한 예외 처리
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division by zero.');
}
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\n";
?>
위의 예는 다음을 출력합니다.
0.2
First finally.
Caught exception: Division by zero.
Second finally.
Hello World
예제 #6 finally
블록과 return 간의 상호 작용
<?php
function test() {
try {
throw new Exception('foo');
} catch (Exception $e) {
return 'catch';
} finally {
return 'finally';
}
}
echo test();
?>
위의 예는 다음을 출력합니다.
finally
예제 #7 중첩 예외
<?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();
?>
위의 예는 다음을 출력합니다.
string(4) "foo!"
예제 #8 다중 catch 예외 처리
<?php
class MyException extends Exception { }
class MyOtherException extends Exception { }
class Test {
public function testing() {
try {
throw new MyException();
} catch (MyException | MyOtherException $e) {
var_dump(get_class($e));
}
}
}
$foo = new Test;
$foo->testing();
?>
위의 예는 다음을 출력합니다.
string(11) "MyException"
예제 #9 잡힌 변수 생략
PHP 8.0.0 이상에서만 허용됩니다.
<?php
class SpecificException extends Exception {}
function test() {
throw new SpecificException('Oopsie');
}
try {
test();
} catch (SpecificException) {
print "A SpecificException was thrown, but we don't care about the details.";
}
?>
예제 #10 잡힌 변수 생략
PHP 8.0.0 이상에서만 허용됩니다.
<?php
class SpecificException extends Exception {}
function test() {
do_something_risky() or throw new Exception('It did not work');
}
try {
test();
} catch (Exception $e) {
print $e->getMessage();
}
?>