2012-12-19 2 views
8

나는 PHP 스크립트를 실행하는 동안 스크립트는 예외를 throw 할 수 있습니다. 내 PHP가 중단 된 위치에서 다시 시작하도록합니다 (예외가 발생했던 곳).예외 PHP를 실행 후 예외 스크립트

동일한 실행 코드를 코드의 "catch"부분에 넣어야합니까?

예에서입니다 연결이

function someCode(){ 
     $pdostmt = $this->prepare($this->sql); 
     if($pdostmt->execute($this->bind) !== false) { 
      if(preg_match("/^(" . implode("|", array("select", "describe", "pragma")) . ") /i", $this->sql)) 
       return $pdostmt->fetchAll($this->fetchOption); 
      elseif(preg_match("/^(" . implode("|", array("delete", "insert", "update")) . ") /i", $this->sql)) 
       return $pdostmt->rowCount(); 
    } 
    try { 
     someCode(); 
     } 
    } catch (PDOException $e) { 
     //re-execute same code as within the try clause? 
     someCode(); 
    } 
+2

당신이하려는 일에 대한 예를 들려 줄 수 있습니까? 리팩토링하면 도움이 될 것입니다. –

+5

코드가 발생했거나 발생하지 않았습니다. – moonwave99

+0

'try' 블록은 많은 문장을 포함 할 수 있습니다. 어느 것이 예외를 유발했는지 알 수는 있지만 사소하지는 않습니다. 무엇을 성취하려고합니까? –

답변

21

먼저 하나는을 잡은하지 않을 경우 예외 은 치명적이다 명확 있는지 확인해야한다. 예외를 잡으면 이 아니라 중지 스크립트가 실행됩니다. try 블록에서 스택 프레임을 중지하고 제어를 catch 블록으로 전달합니다. 거기에서 스크립트가 정상적으로 실행됩니다. 예외가 잡힌 후 예외를 캐치하여

여기에서 우리는 여전히

try { 
    echo "Try...\n"; 
    throw new Exception("This is an exception"); 
} catch(Exception $e) { 
    echo "Exception caught with message: " . $e->getMessage() . "\n"; 
} 

echo "Script is still running..."; 

뭘 할 수 있습니다 것은 exception handler입니다 ... 정상적인 스크립트 실행을 다시 시작합니다. 당신은 다음과 같은 작업을 수행 할 수 try/catch 블록에서 각각의 예외를 처리 할 필요가 없도록 ...

function myExceptionHandler($e) { 
    echo "Uncaught exception with message: " , $e->getMessage(), "\n"; 
} 

set_exception_handler('myExceptionHandler'); // Registers the exception handler 

throw new Exception("This is Exception 1"); 
throw new Exception("This is Exception 2"); 
throw new Exception("This is Exception 3"); 
echo "The script is still running..."; 

편집 예외 핸들러를 사용하려면 : 귀하의 질문에 명확히 후을 내가 언급해야한다고 생각 당신이 원하는 것은 예외 핸들러가 아니지만 실제로는 예외를 사용하고 싶지는 않습니다. 당신이하려는 것은 예외를 던지기를 전혀 요구하지 않습니다. PDO를 예외 모드로 두지 마십시오. 그렇게하려는 오류가 발생하면 PDO를 처리하십시오. 예외는 예외적 인 오류를 처리하는 데에만 사용해야합니다. 예외의 요점은 약속을 지키는 것입니다. 예를 들어, 함수가 항상 PDOStatement 객체를 반환한다는 약속을하고 그것이 가능하지 않은 경우가있을 경우 예외를 throw하는 것이 좋습니다. 이것은 우리가 우리의 약속을 지킬 수없는 지점에 도달했습니다 것을 발신자가 알 수 있습니다.

당신이 원하는 것은 기본 오류 처리입니다

...

function someCode(){ 
     $pdostmt = $this->prepare($this->sql); 
     if($pdostmt->execute($this->bind) !== false) { 
      if(preg_match("/^(" . implode("|", array("select", "describe", "pragma")) . ") /i", $this->sql)) 
       return $pdostmt->fetchAll($this->fetchOption); 
      elseif(preg_match("/^(" . implode("|", array("delete", "insert", "update")) . ") /i", $this->sql)) 
       return $pdostmt->rowCount(); 
     } else { 
      return false; 
     } 
} 

while (someCode() === false) { 
    /* Call someCode() until you get what you want */ 
} 
+0

그래서 마지막으로 PHP 5.5의 목적은 무엇입니까? 나는 항상 그것을 실행을 계속하고 잡기를 멈추지 않는 잡기를 보증하기 위해 거기에 있었지만. – MCHam

+0

@MCHam'finally'의 목적은'try' 블럭 내부에 Exception이 던져 지는지 여부와'catch' 블럭 안에서 처리되는지 여부에 관계없이 ** 코드 블럭이 ** 작동 함을 보장하는 것입니다. ** 단지 발견되지 않은 예외는 치명적입니다 ** – Sherif

+0

PHP 5.5 이상에서는 try 블록에 return 문이 있으면 실제로 반환되기 전에 finally 블록을 실행합니다 (catch 블록 뒤의 코드가있는 경우에는 try 블록은 해당 코드를 실행하지 않습니다). finally 블록은 예외가 처리되는지 여부에 관계없이 try 코드가 반환되는지 또는 계속 수행되는지에 관계없이 코드가 호출되도록합니다. – Russ

0

당신은 실행에서 예외를 얻을 수 없습니다 경우 시도 캐치의 마지막 부분을 사용할 수 있습니다 시간 초과에 대한 실패의 MySQL에 연결 말할 수 있습니다. 모든

try { 
    // some crashing code 
} catch (Exception $e) { 
    //some catch code 
} finally { 
    //code that will run anyways. 
} 
+0

마침내 PHP 5.5의 기능이 아닙니다 (실제로 아무도 아직 가지고 있지 않습니다)? – Smar

+0

... 예외가 발생했을 때 정확한 시점에서 다시 시작하지 않습니다. 하드 코딩 된 명령문 집합 만 실행합니다. –

+0

두 주석 모두에 예. – jaudette

3

나는 당신이 그것을가 발생되는 함수에서 예외를 처리 할 수없는 것을 가정 할 것입니다. 예외가 발생한 곳에서 다시 시작하려면 예외를 처리해야합니다. 다른 것은 당신이나 다른 사람이 프로젝트에서 작업하는 데 혼란을 야기하는 잘못된 코딩입니다. 범위 문제 때문에 자체 함수에서 처리 할 수 ​​없기 때문에 예외를 트리에 올려야합니다.

내가 확장 할 예제에 관해서. 연결이 발생할 수 없기 때문에 작업을 계속할 수 없다고 말합니다.실제로 우리는 괄시 적으로 기능을 다시 시도하기를 원하지 않습니다. 왜냐하면 우리는 본질적으로 연결을 지속적으로 시도하는 행 포인트를 만들 것이므로 우리는 사용자에게 알릴 수있는 트리의 위쪽에있는 catch 블록을 사용하고 사용자가 원하는 것을 결정하게합니다 . 이렇게하면 올바른 위치에 catch 블록을 사용하여 데이터를 저장할 수 있으므로 데이터를 복원하고 나중에 실행할 수 있습니다. 실제로 우리는 try 블록 이전의 시점에서 끝내기를 원합니다.

이렇게하면 훨씬 더 명확한 실행 경로가 제공됩니다. 때로는 기능/방법을 다시 생각해야 올바르게 한 가지를 할 수 있습니다.

귀하의 질문에 대한 답변을 간단하고 뻔뻔스럽게 작성하십시오. 아니요, catch 블록에서 try (ed) 함수를 호출하는 것은 좋지 않습니다. 간단한 이유는 예외를 잡기위한 try 블록이 없기 때문입니다. 예외는 더 의미있는 오류 처리를 가져오고 true 및 false를 반환으로 전달합니다. 그러나, 그것은 당신이 그들을 다룰 때 완전한 원을 돌아야 만한다는 것을 의미합니다.

이제 대체 예를 들어 보겠습니다. 연결할 수있는 서버가 여러 개 있다고 가정하고 목록에 try/catch를 넣고 루프를 실행하려고하면 catch는 해당 예외를 확인하고 수행합니다. 다음 루프를 실행하기 전에 정리하십시오. 다른 예외가 발생하면 예외가 throw됩니다. 당신이 찾고있는 것을 달성 할 수있는 올바른 방법은 이와 같습니다.

function someCode() { 
    $pdostmt = $this->prepare($this->sql); 

    while($status == false) { 
     try { 
      $status = $pdostmt->execute($this->bind) 

     } catch (PDOException $e) { 
      if($e->getMessage("What ever the error message is") { 
       //Fix it here 
      } else { 
       throw $e; 
      } 
     } 
    } 
    //Do other stuff 
    return $data; //or true/false 
} 
+0

"예외가 발생한 곳에서 다시 시작하려면 예외를 처리해야합니다." - tl을 원하면 누구에게나; dr - 중요한 부분이고 100 % 올바른 방향입니다. –