php: 예외를 포착하고 실행을 계속할 수 있습니까?
예외를 포착하여 스크립트 실행을 계속할 수 있습니까?
네, 하지만 실행하는 내용에 따라 달라집니다.
예.
try {
a();
b();
}
catch(Exception $ignored){
}
c();
c()
항상 실행됩니다., 만약 ★★★★★★★★★★★★★★★★.a()
의해 예외 「」가 합니다.b()
는 실행되지 않습니다.
은 건건 the 에 넣어 주세요.try
서로 의지하는 블록입니다.예.b
의 a
라고 하는 것은 말이 안 된다.b
그 try-catch
네, 실행을 계속하려는 곳에서 예외를 포착하면 됩니다.
try
{
SomeOperation();
}
catch (SomeException $ignored)
{
// do nothing... php will ignore and continue
// but maybe use "ignored" as name to silence IDE warnings.
}
물론 이것은 매우 중요한 오류가 될 수 있는 것을 묵묵히 폐기하는 문제를 안고 있습니다.일부 조작()이 실패하면 다른 미묘하고 이해하기 어려운 문제가 발생할 수 있지만 예외를 자동으로 폐기할지는 알 수 없습니다.
물론입니다.
try {
throw new Exception('Something bad');
} catch (Exception $e) {
// Do nothing
}
예외에 대한 PHP 문서를 읽어보실 수 있습니다.
php >7
새로운 인터페이스인 슬로우 가능
try {
// Code that may throw an Exception or Error.
} catch (Throwable $t) {
// Handle exception
}
echo "Script is still running..."; // this script will be executed.
네.
try {
Somecode();
catch (Exception $e) {
// handle or ignore exception here.
}
그러나 php에는 예외와는 다른 에러 코드도 있습니다.이것은 php가 oop 프리미티브를 가지기 전의 레거시 홀드오버입니다.대부분의 라이브러리의 빌트인에서는, 에러 코드가 발생하고 있습니다만, 예외는 발생하지 않습니다.에러 코드를 무시하려면 , @: 가 붙은 함수를 호출합니다.
@myfunction();
PHP 8+의 경우 검출된 예외에 대해 변수 이름을 생략할 수 있습니다.
PHP 8.0.0에서는 검출된 예외에 대한 변수 이름은 옵션입니다.지정하지 않으면 캐치 블록은 계속 실행되지만 던져진 개체에 액세스할 수 없습니다.
다음과 같이 할 수 있습니다.
try {
throw new Exception("An error");
}
catch (Exception) {}
또 다른 관점에서는 처리 코드에서 예외를 반환하는 것이 아니라 예외를 반환하는 것입니다.
내가 쓰는 템플릿 틀로 이걸 해야 했어사용자가 데이터에 존재하지 않는 속성에 액세스하려고 하면, 저는 오류를 던지지 않고 처리 기능 깊은 곳에서 반환합니다.
그 후, 이 반환된 에러를 송신해, try()를 catch() 할 것인지, 아니면 그냥 속행할 것인지를, 콜 코드로 결정할 수 있습니다.
// process the template
try
{
// this function will pass back a value, or a TemplateExecption if invalid
$result = $this->process($value);
// if the result is an error, choose what to do with it
if($result instanceof TemplateExecption)
{
if(DEBUGGING == TRUE)
{
throw($result); // throw the original error
}
else
{
$result = NULL; // ignore the error
}
}
}
// catch TemplateExceptions
catch(TemplateException $e)
{
// handle template exceptions
}
// catch normal PHP Exceptions
catch(Exception $e)
{
// handle normal exceptions
}
// if we get here, $result was valid, or ignored
return $result;
그 결과, 원래의 에러의 콘텍스트를 알 수 있었습니다.이 에러는 맨 위에 던져져 있었습니다.
다른 옵션은 커스텀 NullObject 또는 UnknownProperty 객체를 반환하여 catch()를 트립하기 전에 그것과 비교하는 것입니다.그러나 어쨌든 오류를 다시 던질 수 있고 전체적인 구조를 완전히 제어할 수 있다면 이는 try/catch를 계속할 수 없는 문제를 해결하는 좋은 방법이라고 생각합니다.
오래된 질문입니다만, 과거에 VBA에서 php로 이동할 때 가졌던 질문입니다.여기서 "GoTo"는 "Resume"와 함께 루프 "On Error"를 재입력하여 기능을 처리하도록 할 수 있습니다.
php에서는 약간의 시행착오를 거친 후 nested try{} catch{}를 사용하여 중요한 프로세스와 중요하지 않은 프로세스, 또는 상호의존적인 클래스 호출에 대해 에러의 시작을 추적할 수 있습니다.예를 들어 함수 b가 함수 a에 의존하지만 함수 c가 있으면 좋지만 프로세스를 정지해서는 안 됩니다.또한 알고 싶습니다.이 세 가지 결과에 관계없이 저는 다음과 같이 하겠습니다.
//set up array to capture output of all 3 functions
$resultArr = array(array(), array(), array());
// Loop through the primary array and run the functions
foreach($x as $key => $val)
{
try
{
$resultArr[$key][0][] = a($key);
$resultArr[$key][1][] = b($val);
try
{ // If successful, output of c() is captured
$resultArr[$key][2][] = c($key, $val);
}
catch(Exception $ex)
{ // If an error, capture why c() failed
$resultArr[$key][2][] = $ex->getMessage();
}
}
catch(Exception $ex)
{ // If critical functions a() or b() fail, we catch the reason why
$criticalError = $ex->getMessage();
}
}
이제 각 키의 결과 어레이를 루프하여 결과를 평가할 수 있습니다.a() 또는 b()에 중대한 장애가 있는 경우.
$resultArr 내에서 중대한 장애가 발생하기 전에 어느 정도 도달했는지에 대한 참조 포인트가 남아 있습니다.또한 예외 핸들러가 올바르게 설정되어 있으면 장애가 발생한 것이 a()인지 b()인지를 알 수 있습니다.
c()가 실패해도 루프는 계속 진행됩니다.여러 포인트에서 c()가 실패했을 경우 추가 포스트 루프 로직을 사용하여 $resultArr[$key][2]를 조회함으로써 각 반복에서 c()가 동작했는지 오류가 있었는지 확인할 수 있습니다.
할 수 있지만 경고하는데 많은 사람들이 이 방법을 상당히 악하다고 생각한다.
// https://stackoverflow.com/a/66377817/578023
function is_same(&$a, &$b): bool {
$_ = [ &$a, &$b ];
return
\ReflectionReference::fromArrayElement($_, 0)->getId() ===
\ReflectionReference::fromArrayElement($_, 1)->getId();
}
function attempt_risky_action($collection){
$cursor=NULL;
$resuming = false;
resume:
try{
foreach($collection as $item){
if($resuming && !is_same($cursor,$item) ){
continue; // some things have better ways to skip ahead, especially an array index
}
else {
$resuming = false;
$cursor=&$item; // main concept is to remember where you are in the iteration
} // in some situation you may have to use references, &item
// your normal loop here
.
.
.
}
} catch( Exception $e){
$resuming = repair_something($e, $collection); // returns false if your repair ran out of ideas
if($resuming)
goto resume;
}
unset($cursor);
}
가장 이상적인 것은 이 제품을unset($cursor);
을 호출하다.finally{}
블록, 하지만 솔직히 난 그게 손쉬운 goto랑 어떻게 놀지 모르겠어.
플로우를 끊었기 때문에 실행되는 경우 커서가 계속 존재하기 위해 조건부 로직이 필요합니다.루프 내에 return 스테이트먼트가 있는 경우 콜에 최종 블록을 사용해야 합니다.unset($cursor)
-- 또는 메모리 누설이 발생합니다.
한편, 재미는 떨어지지만, 루프 전체를 네스트 하는 것만으로 같은 트릭을 실행할 수 있습니다.do{ try/catch } while($resuming)
그것이 말 그대로 당신의 실행을 되돌리는 것은 아니지만, 그것은 위험을 감수하지 않고 정확히 같은 효과를 발휘한다.
is_same()
https://stackoverflow.com/a/66377817/578023 에서
function attempt_risky_action($collection){
$cursor=NULL;
$resuming = false;
do{
try{
foreach($collection as $item){
if($resuming && !is_same($cursor,$item) ){
continue;
}
else {
$resuming = false;
$cursor=&$item;
}
// your loop here
}
} catch( Exception $e){
$resuming = repair_something($e, $collection); // returns false if your repair ran out of ideas
}
finally{
if(!$resuming){
unset($cursor);
}
}
} while($resuming);
}
마지막 방법, 그림이 아닙니다.PHP를 사용할 수 있습니다.reset()
,prev()
,current()
,next()
,end()
능력
되는 코드 에 try수 " "/"를 사용합니다.prev()
하다
언급URL : https://stackoverflow.com/questions/2132759/php-catch-exception-and-continue-execution-is-it-possible
'programing' 카테고리의 다른 글
어디에 isset() 및 !empty()를 사용해야 합니까? (0) | 2023.01.31 |
---|---|
함수의 모든 인수를 해당 함수 내에서 단일 개체로 가져올 수 있습니까? (0) | 2023.01.31 |
Java API는 왜 쇼트나 바이트 대신 int를 사용하는가? (0) | 2023.01.21 |
수천 개의 SELECT 쿼리 속도 향상 (0) | 2023.01.21 |
pytest에서 예외가 발생한다고 올바르게 주장하는 방법은 무엇입니까? (0) | 2023.01.21 |