ti-enxame.com

Posso usar try-catch-finalmente assim?

Estou a usar try-catch há anos, mas nunca aprendi como e quando usar finally, porque nunca entendi o sentido de finally (li livros ruins)?

Quero perguntar sobre o uso de finally no meu caso.

Meu exemplo de código deve explicar tudo:

$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);
}

É este o uso correto de finalmente?

Pergunta mais precisa:

Devo usar finally (no futuro PHP ou outras linguagens) para manipular operações "crie algo se não existir"?

15
Kamil

Finalmente, sempre será executado, portanto, neste caso, não é o seu objetivo, pois a execução normal reabriria o arquivo uma segunda vez. O que você pretende fazer seria alcançado da mesma maneira (mais limpa) se você

$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);
}

Então o manual diz:

Para o benefício de alguém que nunca encontrou os bloqueios anteriores, a principal diferença entre eles e o código normal após um bloco try/catch é que eles serão executados mesmo que o bloco try/catch retorne o controle à função de chamada.

Isso pode ser feito se:

  • código se o seu bloco try contiver um tipo de exceção que você não captura
  • você lança outra exceção no seu bloco de captura
  • sua tentativa ou captura de chamadas em bloco retornam

Finalmente, seria útil nesse tipo de cenário:

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();
    }
}

=> se você precisar fechar o manipulador de arquivos nesse caso, ou algum recurso em geral.

31
mika

finally não foi introduzido em PHP até a versão 5.5 que ainda não foi lançada, portanto é por isso que você ainda não viu nenhum exemplo). e a versão alfa do PHP 5.5 você ainda não pode usar finally).

Do manual ( exceções )

Em PHP 5.5 e posterior, um bloco final também pode ser especificado após os blocos catch. O código dentro do bloco final sempre será executado após os blocos try e catch, independentemente de uma exceção ter sido jogado e antes da execução normal continuar.

Exemplo do manual do uso de 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

Finalmente significa o que você quer fazer Finalmente.

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
}

Não importa o que aconteça (independentemente de uma exceção ter sido lançada) dentro de try ou catch, 'Finalmente o código' será executado. Portanto, não adianta usar o mesmo código em 'try' e 'finalmente'. Isso simplesmente responde à sua pergunta?

0
Mayukh Roy

Eu só quero indicar que, se uma exceção ocorrer no bloco try, a exceção será gerada corretamente, mesmo que o bloco finally esteja presente. A utilidade do bloco finally é para recursos limpos e livres. Eu acho que é melhor usar quando, por exemplo, você faz o upload de um arquivo, mas ocorre um erro:

$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
}

Como você pode ver, não importa o que aconteça, o arquivo temporário será excluído corretamente.
Se emularmos a cláusula finally na versão mais antiga do PHP, devemos escrever algo como isto:

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

Observe que a exceção foi lançada novamente, caso o bloco catch capturasse alguma coisa. Não está claro como a versão finally, mas funciona da mesma maneira.

0
Iazel