web-dev-qa-db-ja.com

「最終的に」というキーワードは、PHPでどのように使用されるのですか?

したがって、私はPHPオンラインマニュアルで今日の例外について読んでいますが、finallyキーワードの目的または真の必要性をまだ理解していないことに気づきました。ここでいくつかの投稿を読んだので、私の質問は少し異なります。

私は最終的にこのように使用できることを理解しています:

_function hi(){
    return 'Hi';
}


try {
    throw new LogicException("Throw logic \n");
} catch (InvalidArgumentException $e) {
    echo $e->getMessage(); 
}

echo hi();
_

出力:

_Fatal error:  Uncaught LogicException: Throw Logic in C:\Users\...a.php:167
Stack trace:
#0 {main}
  thrown in C:\Users\...a.php on line 167
_

したがって、この場合は関数hi();です。実行されておらず、正当な理由があります。例外が処理されない場合、phpインタープリターがスクリプトを停止することを理解しています。良い。これまで読んだところから、ようやく関数hi()を実行できるようになりました。例外が処理されない場合でも(理由はわかりません)

だから、これは私が理解しています。

_try {
    throw new LogicException("Throw logic \n");
} catch (InvalidArgumentException $e) {
    echo $e->getMessage(); 
}finally{
    echo hi();
}
_

出力:

_Hi
Fatal error:  Uncaught LogicException: Throw Logic in C:\Users\...a.php:167
Stack trace:
#0 {main}
  thrown in C:\Users\...a.php on line 167
_

これは、例外エラーと関数からの「hi」メッセージである必要があります。私がこれを使用する方法がわからない場合でも同様です。ただし、_LogicExceptionをcatch _(LogicException $e)_でキャッチし、例外がスローされない場合でも、関数が実行されていることがわかり、「hi」メッセージが表示されます。 。この例のように

_try {
    throw new LogicException("Throw logic \n");
} catch (LogicException $e) {
    echo $e->getMessage(); 
}finally{
    echo hi();
}
_

出力

_// Throw logic 
// Hi
_

したがって、Uncaught例外がない場合でも、関数hi()が実行されていることがわかります。なぜ、何のために使用するのですか?最後のブロックは、例外がキャッチされなかった場合の最後の手段として使用されるべきだと思いました。そうでない場合でも、なぜそれを実行するのに使用するのですか?

22
ʎɹnɔɹǝW

finally実行毎回

例外や返品に関係なく

例外

私が見ている一般的な用途の1つは、長時間実行されているワーカーでデータベース接続を閉じることです-これを毎回(例外ありまたはなしで)実行して、データベースサーバーが新しい接続を受け入れるのをブロックするぶら下がり接続になってしまわないようにします。

この疑似コードを考えてみましょう:

try {
   $database->execute($sql);
} finally {
   $database->close();
}

ここでは、常にデータベース接続を閉じます。通常のクエリであれば、成功後に接続を閉じます。エラーのあるクエリの場合は、例外がスローされた後も終了します。

catchがログを記録する例を以下に示します。

try {
   $database->execute($sql);
} catch (Exception $exception) {
   $logger->error($exception->getMessage(), ['sql' => $sql]);
   throw $exception;
} finally {
   $database->close();
}

これにより、例外の有無に関係なく接続が閉じられます。

この動作は他の言語では異なります。たとえば、.NETでは、catchブロックから例外がスロー/再スローされると、finallyブロックは実行されません

返す

あいまいな動作の1つは、returnステートメントの後にコードを実行する機能です。

ここでは、関数が戻った後に変数を設定できます。

function foo(&$x)
{
    try {
        $x = 'trying';
        return $x;
    } finally {
        $x = 'finally';
    }
}

$bar = 'main';
echo foo($bar) . $bar;

最後に

しかし、割り当てはtryで返されるものになります。

$bar = foo($bar);
echo $bar . $bar;

しようとしている

そして、finallyで戻ると、tryでの戻りがオーバーライドされます。

function baz()
{
    try {
        return 'trying';
    } finally {
        return 'finally';
    }
}

echo baz();

最終的に

noteこの動作はphp 5では異なりました:

ついに
最後に
最終的に

https://3v4l.org/biO4e

26
Jeff Puckett
try {
    throw new LogicException("Throw logic \n"); -> LogicException thrown
} catch (InvalidArgumentException $e) { -> LogicException not catched
    echo $e->getMessage(); 
}finally{
    echo hi(); -> code executed. "Hi" printed out
}

LogicException is here -> Fatal error

したがって、この場合:

try {
    throw new LogicException("Throw logic \n"); -> LogicException thrown
} catch (InvalidArgumentException $e) { -> LogicException not catched
    echo $e->getMessage(); 
}finally{
    echo hi(); -> code executed
    die();
}

dieステートメントと最後のバリエーションのため、致命的なエラーは発生しません。

try {
    throw new LogicException("Throw logic \n"); -> LogicException thrown
} catch (InvalidArgumentException $e) { -> LogicException not catched
    echo $e->getMessage(); 
} catch (LogicException $e) { -> LogicException catched
    echo $e->getMessage(); 
}finally{
    echo hi(); -> code executed
}
1
myxaxa

最後に、例外があるかどうかに関係なく実行する必要があるコードを含める必要があります。

最後に:

try {
   $handle = fopen("file.txt");
   //Do stuff
   fclose($handle);
   return something;
} catch (Exception $e) {
   // Log
   if (isset($handle) && $handle !== false) {
      fclose($handle);
   }     
}

最後に:

try {
   $handle = fopen("file.txt");
   return something;
} catch (Exception $e) {
   // Log
} finally {
   if (isset($handle) && $handle !== false) {
      fclose($handle);
   }     
}

関数が返された後にリソースを解放する必要がある場合に備えて、少し整理を提供します。

これは、次のような場合にさらに役立ちます。

 try {
     $handle = fopen("file.txt");
     if (case1) { return result1; }  
     if (case2) { return result2; }
     if (case3) { return result3; }
     if (case4) { return result4; }

 } finally {
     if (isset($handle) && $handle !== false) {
          fclose($handle);
       }    
 }

この場合、メソッドが戻る直前に他のコードの後に​​実行される単一のfclose呼び出しに戻る前に、必要なすべてのfclose呼び出しを減らすことができます。

0
apokryfos