web-dev-qa-db-ja.com

このようにtry-catch-finallyを使用できますか?

私は何年もtry-catchを使用していますが、finallyのポイントを理解していなかったため、finallyを使用する方法と時期を学んだことはありません(私は悪い本を読んだことがあります)?

私の場合のfinallyの使用についてお聞きします。

私のコード例はすべてを説明するはずです:

$s = "";

$c = MyClassForFileHandling::getInstance();

try
{
    $s = $c->get_file_content($path);
}

catch FileNotFoundExeption
{
    $c->create_file($path, "text for new file");
}

finally
{
    $s = $c->get_file_content($path);
}

最終的にこれは正しい使い方ですか?

より正確な質問:

「存在しない場合に何かを作成する」操作を処理するためにfinally(将来はPHPバージョンまたは他の言語))を使用しますか?

15
Kamil

最後に常に実行されます。通常の実行ではファイルが再度開かれるため、この場合、それは本来の目的ではありません。あなたがやろうとしていることは、あなたがそうすれば同じ(よりきれいな)方法で達成されるでしょう

$s = "";

$c = MyClassForFileHandling::getInstance();

try
{
    $s = $c->get_file_content($path);
}
catch(FileNotFoundExeption $e)
{
    $c->create_file($path, "text for new file");
    $s = $c->get_file_content($path);
}

その後、マニュアルは言う:

最終的にブロックに遭遇したことがない人のために、それらとtry/catchブロックに続く通常のコードとの主な違いは、try/catchブロックが呼び出し元の関数に制御を返す場合でも実行されることです。

これは次の場合に行われる可能性があります。

  • キャッチしない例外タイプがtryブロックに含まれている場合のコード
  • あなたはあなたのキャッチブロックで別の例外を投げます
  • あなたのtryまたはcatchブロック呼び出しが戻ります

最後に、この種のシナリオで役立ちます。

function my_get_file_content($path)
{
    try
    {
        return $c->get_file_content($path);
    }
    catch(FileNotFoundExeption $e)
    {
        $c->create_file($path, "text for new file");
        return $c->get_file_content($path);
    }
    finally
    {
        $c->close_file_handler();
    }
}

=>この場合、ファイルハンドラ、または一般的なリソースを確実に閉じる必要がある場合。

31
mika

finallyは、まだリリースされていないバージョン5.5までPHPに導入されていなかったため、なぜそれを使った例もまだ見ていません。そのため、 PHP 5.5のアルファ版は、まだfinallyを使用できません。

マニュアルから( 例外

PHP 5.5以降では、catchブロックの後にfinallyブロックも指定できます。finallyブロック内のコードは、例外が発生したかどうかに関係なく、tryブロックとcatchブロックの後に常に実行されますスローされ、通常の実行が再開する前。

finallyを使用したマニュアルの例

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    else 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';
?>
4
John Conde

最後に、何をしたいのかを意味します。

try
{
    $s = $c->get_file_content($path);
}

catch FileNotFoundExeption
{
    $c->create_file($path, "text for new file");
}

finally
{
    //Create a pdf with my file
    //or, Rename my file
    //or, store my file into Database
}

Tryまたはcatch内で何が起こっても(例外がスローされたかどうかに関係なく)、「最終的にコード」が実行されます。したがって、「try」と「finally」で同じコードを使用する意味はありません。これは単にあなたの質問に答えますか?

0
Mayukh Roy

tryブロックで例外が発生した場合、finallyブロックが存在していても例外が正しく発生するように指定します。 finallyブロックの有用性は、クリーンで空きリソースのためです。たとえば、ファイルをアップロードしたときにエラーが発生した場合に最適です。

$tmp_name = null;
try {
    $tmp_name = tempnam(UPLOAD_DIR, 'prefix');
    move_uploaded_file($file['tmp_name'], $tmp_name);
    ImageManager::resize($tmp_name, $real_path, $width, $height); // this will rise some exception
}
finally {
    if($tmp_name)
        unlink($tmp_name); // this will ensure the temp file is ALWAYS deleted
}

ご覧のように、このようにして、何が起こっても、一時ファイルは正しく削除されます。
古いバージョンのPHPでfinally句をエミュレートする場合は、次のように記述する必要があります。

// start finally
catch(Exception $ex) {
}
if($tmp_name)
    unlink($tmp_name);
if( isset($ex) )
    throw $ex;
// end finally

catchブロックが何かをキャッチした場合に備えて、例外が再スローされていることに注意してください。 finallyバージョンとしては明確ではありませんが、同じように機能します。

0
Iazel