Undantag

Från Wiki.linux.se
Version från den 20 augusti 2024 kl. 08.48 av Admin (diskussion | bidrag) (→‎Innehållsförteckning)
(skillnad) ← Äldre version | Nuvarande version (skillnad) | Nyare version → (skillnad)
Hoppa till navigering Hoppa till sök

Undantag

Innehållsförteckning

Utöka undantag

PHP har en undantagsmodell som liknar den i andra programmeringsspråk. Ett undantag kan kastas och fångas inom PHP. Kod kan omges av ett try-block för att underlätta hantering av potentiella undantag. Varje try måste ha minst ett motsvarande catch- eller finally-block.

Om ett undantag kastas och dess nuvarande funktionsomfång inte har något catch-block, kommer undantaget att "bubbla upp" genom anropsstacken till den anropande funktionen tills det hittar ett matchande catch-block. Alla finally-block som det stöter på längs vägen kommer att köras. Om anropsstacken avvecklas hela vägen till det globala omfånget utan att stöta på ett matchande catch-block, kommer programmet att avslutas med ett fatalt fel om inte en global undantagshanterare har ställts in.

Det kastade objektet måste vara en instans av Throwable. Försök att kasta ett objekt som inte är det resulterar i ett fatalt fel i PHP.

Från och med PHP 8.0.0 är throw-nyckelordet ett uttryck och kan användas i vilket uttryckssammanhang som helst. I tidigare versioner var det ett uttalande och krävde att det var på en egen rad.

catch

Ett catch-block definierar hur man ska svara på ett kastat undantag. Ett catch-block definierar en eller flera typer av undantag eller fel det kan hantera, och eventuellt en variabel som undantaget ska tilldelas. (Variabeln var obligatorisk före PHP 8.0.0.) Det första catch-block som ett kastat undantag eller fel stöter på som matchar typen av det kastade objektet kommer att hantera objektet.

Flera catch-block kan användas för att fånga olika klasser av undantag. Normal körning (när inget undantag kastas inom try-blocket) kommer att fortsätta efter det sista definierade catch-blocket i sekvensen. Undantag kan kastas (eller kastas om) inom ett catch-block. Om inte, fortsätter körningen efter det catch-block som utlöste.

När ett undantag kastas, kommer koden efter uttalandet inte att köras, och PHP kommer att försöka hitta det första matchande catch-blocket. Om ett undantag inte fångas, kommer ett fatalt fel i PHP att utfärdas med ett meddelande om "Uncaught Exception ...", såvida inte en hanterare har definierats med set_exception_handler().

Från och med PHP 7.1.0 kan ett catch-block specificera flera undantag med hjälp av pipetecknet (|). Detta är användbart när olika undantag från olika klasshierarkier hanteras på samma sätt.

Från och med PHP 8.0.0 är variabelnamnet för ett fångat undantag valfritt. Om det inte anges kommer catch-blocket fortfarande att köras men kommer inte att ha tillgång till det kastade objektet.

finally

Ett finally-block kan också specificeras efter eller istället för catch-block. Kod inom finally-blocket kommer alltid att köras efter try- och catch-blocken, oavsett om ett undantag har kastats eller inte, och innan normal körning återupptas.

En anmärkningsvärd interaktion är mellan finally-blocket och ett return-uttryck. Om ett return-uttryck påträffas inom antingen try- eller catch-blocken, kommer finally-blocket fortfarande att köras. Dessutom utvärderas return-uttrycket när det påträffas, men resultatet kommer att returneras efter att finally-blocket har körts. Om finally-blocket också innehåller ett return-uttryck, returneras värdet från finally-blocket.

Global undantagshanterare

Om ett undantag tillåts bubbla upp till det globala omfånget, kan det fångas av en global undantagshanterare om sådan har ställts in. Funktionen set_exception_handler() kan ställa in en funktion som kommer att anropas istället för ett catch-block om inget annat block anropas. Effekten är i princip densamma som om hela programmet var inneslutet i ett try-catch-block med den funktionen som catch.

Noter

Notera:

Interna PHP-funktioner använder främst felrapportering, endast moderna objektorienterade tillägg använder undantag. Fel kan dock enkelt översättas till undantag med ErrorException. Denna teknik fungerar dock endast med icke-fatala fel.

Exempel #1 Omvandla felrapportering till undantag

<?php
function exceptions_error_handler($severity, $message, $filename, $lineno) {
    throw new ErrorException($message, 0, $severity, $filename, $lineno);
}

set_error_handler('exceptions_error_handler');
?>

Tips: Standard PHP-biblioteket (SPL) tillhandahåller ett stort antal inbyggda undantag.

Exempel

Exempel #2 Kasta ett undantag

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Fångat undantag: ',  $e->getMessage(), "\n";
}

// Fortsätt körning
echo "Hej Världen\n";
?>

Ovanstående exempel kommer att producera:

0.2
Fångat undantag: Division by zero.
Hej Världen

Exempel #3 Undantagshantering med ett finally-block

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}

try {
    echo inverse(5) . "\n";
} catch (Exception $e) {
    echo 'Fångat undantag: ',  $e->getMessage(), "\n";
} finally {
    echo "Första finally.\n";
}

try {
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Fångat undantag: ',  $e->getMessage(), "\n";
} finally {
    echo "Andra finally.\n";
}

// Fortsätt körning
echo "Hej Världen\n";
?>

Ovanstående exempel kommer att producera:

0.2
Första finally.
Fångat undantag: Division by zero.
Andra finally.
Hej Världen

Exempel #4 Interaktion mellan finally-block och return

<?php

function test() {
    try {
        throw new Exception('foo');
    } catch (Exception $e) {
        return 'catch';
    } finally {
        return 'finally';
    }
}

echo test();
?>

Ovanstående exempel kommer att producera:

finally

Exempel #5 Nästlade undantag

<?php

class MyException extends Exception { }

class Test {
    public function testing() {
        try {
            try {
                throw new MyException('foo!');
            } catch (MyException $e) {
                // kasta om det
                throw $e;
            }
        } catch (Exception $e) {
            var_dump($e->getMessage());
        }
    }
}

$foo = new Test;
$foo->testing();

?>

Ovanstående exempel kommer att producera:

string(4) "foo!"

Exempel #6 Hantering av flera undantag i catch

<?php

class MyException extends Exception { }

class MyOtherException extends Exception { }

class Test {
    public function testing() {
        try {
            throw new MyException();
        } catch (MyException | MyOtherException $e) {
            var_dump(get_class($e));
        }
    }
}

$foo = new Test;
$foo->testing();

?>

Ovanstående exempel kommer att producera:

string(11) "MyException"

Exempel #7 Utelämna den fångade variabeln

Endast tillåtet i PHP 8.0.0 och senare.

<?php

class SpecificException extends Exception {}

function test() {
    throw new SpecificException('Oopsie');
}

try {
    test();
} catch (SpecificException) {
    print "Ett SpecificException kastades, men vi bryr oss inte om detaljerna.";
}
?>

Exempel #8 Throw som ett uttryck

Endast tillåtet i PHP 8.0.0 och senare.

<?php

function test() {
    do_something_risky() or throw new Exception('Det fungerade inte');
}

try {
    test();
} catch (Exception $e) {
    print $e->getMessage();
}
?>


Sidslut

Orginalhemsidan på Engelska : https://www.php.net/manual/en/language.exceptions.php
PHP
Språkreferens
Språkreferens#Undantag


Det här är en maskinöversättning av PHP-manualen till svenska. Om du hittar fel är vi tacksamma om du rapporterar dem via formuläret som finns på https://www.linux.se/kontaka-linux-se/