2017-01-12 50 views
6

Tak, czytałem o wyjątkach dzisiaj w podręczniku online PHP i zdałem sobie sprawę, że jeszcze nie rozumiem celu lub prawdziwej konieczności słowa kluczowego finally. Czytałem tutaj niektóre posty, więc moje pytanie jest nieco inne.W jaki sposób keywod "w końcu" ma być użyty w PHP?

Rozumiem, że możemy użyć w końcu w ten sposób:

function hi(){ 
    return 'Hi'; 
} 


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

echo hi(); 

wyjściowa:

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 

Tak więc, w tym przypadku hi function(); nie jest wykonywany i nie bez powodu. Rozumiem, jeśli wyjątek nie jest obsługiwany interpreter php zatrzymuje skrypt. dobry. Tak daleko od tego, co czytam, w końcu pozwala nam na wykonanie funkcji hi(); nawet jeśli wyjątek nie jest obsługiwany (nawet jeśli nie wiem dlaczego)

Więc, ten rozumiem.

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

wyjściowa:

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 

na ten błąd powinien wyjątek, a także „cześć” wiadomość z funkcji, nawet nie wiem dowolny wykorzystanie do tego. Ale to, czego nie podkreślam, nawet jeśli złapiemy LogicException z haczykiem (LogicException $e) i nie wyrzuciliśmy żadnych wyjątków, zobaczylibyśmy funkcję, która jest wykonywana, a zobaczylibyśmy wiadomość "cześć". jak w tym przykładzie

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

wyjścia

// Throw logic 
// Hi 

Tak, nadal widzimy funkcja hi() wykonany chociaż nie mamy Uncaught wyjątki. Dlaczego i jaki jest tego pożytek? Myślałem, że blok w końcu miał być użyty jako ostateczność w przypadku, gdyby wyjątki nie zostały złapane, nawet jeśli tak nie było, to po co to uruchamiać?

+0

Co wersja PHP jest używana? Prawdziwa funkcjonalność 'finally' nie została dodana przed PHP 5.5. –

+0

@AlecGordon php 7.0.1 –

+0

Oh, to dziwne. Zgodnie z [tą analizą] (https://adayinthelifeof.nl/2013/02/12/php5-5-trycatchfinally/) ostatni blok powinien zostać wydrukowany przed nieprzechwyconym wyjątkiem. –

Odpowiedz

2

Blok finally ma być użyty, gdy chcesz wykonać kod, niezależnie od tego, czy został zgłoszony wyjątek, czy nie.

Jednym z bardziej powszechnych zastosowań, jakie widzę, jest zamykanie połączenia z bazą danych - chcesz, aby tak się działo za każdym razem (z wyjątkiem lub bez wyjątku), aby nie kończyło się na wiszącym połączeniu blokującym serwer bazy danych przed akceptowaniem nowe połączenia.

Rozważmy ten pseudo-kod:

try { 
    $database->execute($sql); 
} catch (Exception $exception) { 
    $logger->log($exception->getMessage()); 
    throw $exception; 
} finally { 
    $database->close(); 
} 
+1

Rozumiem to teraz, ale przypadki użycia wydają się bardzo rzadkie. W twoim przykładzie na przykład możesz nadal zamknąć bazę danych przed "rzutem", a to osiągnęłoby to samo. –

+2

@mvrht: Oczywiście możesz zamknąć połączenie DB przed 'throw'formementem_without_ używając' finally', ale chodzi w tym przypadku: Po pierwsze, może nie przechwytujesz _every_ wyjątek, ale tylko pewien typ, to ty nie osiągaj wywołania 'close()' dla innych wyjątków. Po drugie, nawet jeśli złapiesz każdy wyjątek, potrzebujesz gdzieś duplikat kodu (na końcu 'try'block lub po' catch' block) wywołaj 'close()'. Umieszczając to wywołanie w bloku 'finally', musisz napisać tylko jeden raz i jest on wykonywany w każdym przypadku (jeśli wystąpi wyjątek lub nie, jeśli jest catched lub nie). – dwytrykus

0

Wreszcie powinien zawierać dowolny kod, który musi zostać wykonany niezależnie od tego, czy istnieje wyjątek, czy nie.

Bez wreszcie:

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

W końcu:

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

Propozycje trochę decluttering w przypadku, gdy trzeba zwolnić zasób po funkcją powrócił.

ten staje się jeszcze bardziej przydatne w przypadku tak:

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

W tym przypadku można zmniejszyć wszystkie wymagane fclose połączenia przed każdym powrocie do pojedynczego fclose połączenia, które zostanie wykonane tuż przed metody zwraca, ale po każdym innym kodzie.

1
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 

więc w tym przypadku:

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

żaden błąd krytyczny zostanie podniesiony z powodu matrycy oświadczenia i ostatnim wariancie:

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 
}