PHP의 Try / Catch 블록이 예외를 포착하지 못함


97

이 페이지에서이 예제 # 1을 실행하려고합니다 : http://php.net/manual/en/language.exceptions.php

<?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
Fatal error: Uncaught exception 'Exception' with message 'Division by zero.' 
in xxx:
7 Stack trace: #0 xxx(14): inverse(0) #1 {main} thrown in xxx on line 7

내가 사용하고 개발자 환경입니다 UniServer 3.5함께PHP 5.2.3


1
코드를 보여줄 수 있습니까? 이 오류를 얻기 위해 할 수있는 유일한 실수는 잘못된 예외를 포착하는 것입니다 (또는 아무것도 포착하지 않는 것입니다).
Tammo

2
코드가 정확히 동일합니다 (개행 문자를 몇 개 추가했습니다) ... 어쨌든 코드를 다시 테스트 파일에 복사했는데 여기에 동일한 오류 메시지가 있습니다. 0.2 치명적 오류 : 'Division by zero'메시지가있는 Uncaught exception 'Exception' . ' W : \ www \ test.php : 4 스택 추적 : # 0 W : \ www \ test.php (11) : inverse (0) # 1 {main}이 W : \ www \ test.php on line 4에 던져 짐 나는 거기에 무슨 일이 일어나고 있는지 전혀 모른다 ... 아마도 잘못된 PHP 구성?
Krassi

1
일부 이전 확장 버전은 예외 처리에 문제를 일으켰습니다. 5.2.3은 오래되었고 오류 뒤에 버그가있을 수 있습니다. PHP를 업그레이드 할 수 있습니까? UniServer 3.5는 현재 프로덕션 버전이 5.5라는 점을 고려할 때 꽤 오래되었습니다. 3.5가 오타인가요?
2010 년

1
UniServer 릴리스 정보 ( wiki.uniformserver.com/index.php/… )를 보면 3.5는 분명히 오타가 아닙니다. UniServer 5.5로 업그레이드하고 샘플 코드를 다시 시도하십시오.
2010 년

1
outis, 팁 주셔서 감사합니다 :). 이것은 내가 그때 한 일입니다-XAMPP로 전환했습니다 (UniServer의 새 버전이 마음에 들지 않습니다). 3.5는 오타가 아니지만 서버가 완벽하게 작동했기 때문에 업그레이드하는 데 신경 쓰지 않았습니다.
Krassi 2010 년

답변:


217

방금 예외의 이름을 복사 한 것처럼 보였지만 포착하지 못한 정확한 문제가있었습니다. 내 어리석은 실수로 밝혀졌지만 같은 상황에 다른 누군가가있을 경우를 대비해 여기에 내 사례를 게시해야한다고 생각했습니다.

A 라는 네임 스페이스에 예외가 있었고 스크립트는 B 라는 네임 스페이스에있었습니다 . 문제는 A \ MyException 이 (PHP에서) \ B \ A \ MyException (내 스크립트가 B 라는 이름 공간에 있기 때문에 )가 있다는 것입니다. 이 문제를 해결하기 위해해야 ​​할 일은 예외 이름에 백 슬래시 (또는 호출 된 이름)를 추가하여 다음과 같이 보이게하는 것입니다. \ A \ MyException


7
내 실수를 깨닫지 못한 채 며칠을 갔을 것이기 때문에 이것을 게시 해 주셔서 대단히 감사합니다.
tipu

79
이것은 내 문제를 해결했으며 네임 스페이스 코드의 간단한 게으른 catch 블록은 catch (\Exception $e). 백 슬래시 Exception가 없으면 네임 스페이스에 따라 다르며 일치 (또는 포착)되지 않습니다.
joemaller 2013 년

3
게시 해 주셔서 감사합니다!
keepkimi 2013

2
이것을 게시 해 주셔서 감사합니다. 지난 몇 시간 동안 캐치 블록이 작동하지 않는 이유에 대해 미쳐 보았습니다. 주요 안면 손바닥.
Mitch

4
건배! 내 하루를 구했습니다 (그리고 뉴런 ...) :)
야채

67

꽤 오래된 질문이지만 ...

나도이 문제가 있었지만 (그게 내가이 게시물을 찾은 방법이다) 간단한 실험으로 해결책을 찾을 수 있었다. 그냥 변경 시도 Exception\Exception. 나를 위해 일했습니다!

편집하다:

Sivann이 주석에서 지적했듯이 네임 스페이스를 사용하면 동일한 작업을 수행해야합니다. 따라서 use \Exception as Exception;클래스 선언 앞에 넣으 십시오.


훌륭한! :) 아마 알아내는 데 몇 시간이 걸릴 것입니다. 네임 스페이스에 대해서는 생각하지 않았습니다. 감사!
Alexander Gilmanov 2011 년

예! 또한 : "\ Exception을 예외로 사용;" 상단에서 동일한 작업을 수행합니다.
sivann

@ sii-anik sivann이 작성한 것처럼 네임 스페이스를 사용해보십시오.
Enethion

단지 use Exception;그것을해야
디에고 Ponciano

감사합니다! @Enethion
Noamway

32

catch(\Exception $e)대신 넣어보십시오 catch(Exception $e). 잘 모르는 코드를 사용하는 경우, 특히 프레임 워크를 사용하는 경우 기본 PHP 예외를 자체적으로 무시할 수 있으므로 잘못된 경로로 이동하여 원하지 않는 결과. 그냥 넣으면 \Exception기본 PHP 예외를 포착하고 있다는 것을 확신합니다.


@crassi, 내 제안을 시도 했습니까?
Vladimir Despotovic

2
그것은 나를 위해 그것을했다
cljk

20

C # (Csharp)과 같은 다른 언어에서 할 수있는 것처럼 PHP에서 일반적인 try {} catch {} 블록을 사용할 수 없습니다.

이렇게하면 :

try{
    //division by zero
    $number = 5/0;
}
catch(Exception $ex){
    echo 'Got it!';
}

'Got it!'이 표시되지 않습니다. 절대 메시지. 왜? PHP는 항상 "Thrown"이되는 예외를 필요로하기 때문입니다. 자체 오류 처리기를 설정하고 예외를 발생시켜야합니다.

set_error_handler 함수 참조 : http://php.net/manual/es/function.set-error-handler.php


6
PHP는 항상 >> "슬로우"할 수있는 예외) @JaredFarrish 필요가 있기 때문에 << 그것은 단지 (당신은 자신에 의해 예외를 던질 필요), 그리고 내가 무슨 말을했는지, 즉 동일 하
Rowinson 레고

예, 그러나 어떻게 동일하지 않습니까?
Jared Farrish 2011

그 링크는 죽었지 만 유용하다고 생각했습니다 : w3schools.com/php/func_error_set_error_handler.asp
Loathing

PHP 버전 7.3.9에서 $number = 5/0;예외가 발생하지 않습니다. $number로 설정됩니다 INF.
virtualmic

6

내 이니셜은 포착 / 던지는 예외의 이름에 오타가 있지만 코드가 정확히 동일하다면 정확히 무슨 일이 일어나고 있는지 잘 모르겠습니다.

원본 스크립트를 다음과 같이 수정하고 결과를 붙여 넣으십시오. 문제를 좀 더 잘 진단하는 데 도움이됩니다.

<?php

//set up exception handler to report what we didn't catch
function exception_handler($exception) {

    if($exception instanceof MyException) {
        echo "you didn't catch a myexception instance\n";

    } else if($exception instanceof Exception) {
        echo "you didn't catch a exception instance\n";

    } else {
        echo "uncaught exception of type: ".gettype($exception)."\n";
    }

    echo "Uncaught exception: " , $exception->getMessage(), "\n";
}

//install the handler
set_exception_handler('exception_handler');

class MyException extends Exception {
}

function inverse($x) {
    if (!$x) {
        throw new MyException('Division by zero.');
    }
    else return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (MyException $e) {
    echo 'Caught myexception: ',  $e->getMessage(), "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo 'Hello World';
?>

4

다음 구성에서 동일한 문제가 발생했습니다.

PHP 5.2.14 (cli) (빌드 : 2010 년 8 월 12 일 17:32:30) Copyright (c) 1997-2010 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies with eAccelerator v0.9.5. 1 , Copyright (c) 2004-2006 eAccelerator, by eAccelerator

해결책은 eAccelerator를 비활성화하거나 업데이트하는 것입니다. 두 가지를 모두 시도했는데 두 가지 수정 사항이 모두 작동했습니다. 버그는 https://eaccelerator.net/ticket/242(NB . firefox가 SSL 인증서에 대해 불만을 표시 함 )에보고됩니다 .

이제 다음 구성으로 올바르게 try catch를 실행하고 있습니다.

PHP 5.2.4 (cli) (빌드 : 2007 년 10 월 16 일 09:13:35) Copyright (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies with eAccelerator v0.9.6. 1 , Copyright (c) 2004-2010 eAccelerator, by eAccelerator



3

Xdebug에는 설정이 있습니다.

xdebug.show_exception_trace = 1

이것은 try catch 블록에서도 예외를 출력하도록 PHP를 강제합니다. 이것을0


2
제 경우에는 xdebug 모듈을 완전히 비활성화해야했습니다 (xdebug.show_exception_trace 변경만으로는 충분하지 않음).
토마스 Sahlin

이 알림에 감사드립니다. 나는 한동안 완전히 혼란 스러웠다.
Brian Litzinger

3

PHP 7을 사용하는 경우 예외 대신 Throwable이 필요할 수 있습니다.


이것은 다소 오래된 게시물입니다. 답변하기 전에 주제의 날짜를 확인하십시오. 그 외에도 귀하의 답변은 그 자체로 도움이되지 않습니다 :-완전하지 않음-이유 설명 없음
monofone

1
설명은 PHP7이 Exception 대신 Throwable을 사용한다는 것입니다. 이 토론은 제가 문제를 만났을 때 발견 한 첫 번째 토론이며 제가 기여하고 싶었습니다. 이와 같은 댓글은 Stack이 커뮤니티 친화적이지 않은 이유입니다.
user5528384

1
당신을 화나게하려는 것은 내 의도가 아니 었습니다. 이 게시물은 "첫 번째 게시물"리뷰 대기열에 나타 났으며 제 생각에는 다소 오래된 질문에 대한 답변을 게시하는 것이 유용하지 않았습니다. 그리고 Question Throwable은 PHP 세계에서 발명되지도 않았습니다. Throwable이 Exception (및 Error)에 의해 구현 된 인터페이스이므로 잡을 수 있다는 답변을 작성하면 도움이 될 것입니다. 그러나 이것은 예외를 보완하는 것이 아닙니다.
monofone


1

TLDR; use Exception;두 PHP 파일의 상단에 있는지 확인하십시오.


0

나도 이것을 경험하고있다. 나는 Rowinson Gallego로부터 Exception이 던져 져야한다는 코멘트를 읽었습니다. 그래서 다음에서 코드를 수정했습니다.

try
{
  $number = 5/0; //or other exception
}
catch(Exception $e)
{
  throw $e;
}

로 :

try
{
  $number = 5/0; //or other exception
}
catch(Exception $e)
{
  throw new Exception($e->getMessage(),$e->getCode());
}

효과가있다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.