mirror of
https://github.com/macintoshplus/doc-fr.git
synced 2026-03-24 08:52:09 +01:00
565 lines
16 KiB
XML
565 lines
16 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- EN-Revision: 7a75b854c8c52226d38397e7e8177e339fdb273f Maintainer: yannick Status: ready -->
|
|
<!-- Reviewed: no -->
|
|
|
|
<chapter xml:id="language.exceptions">
|
|
<!-- we use our own DTD instead of xmlns="http://docbook.org/ns/docbook" so that we can use
|
|
<sect1 annotations="chunk:false"> -->
|
|
<title>Les exceptions</title>
|
|
<para>
|
|
PHP a une gestion des exceptions similaire à ce qu'offrent les autres
|
|
langages de programmation.
|
|
Une exception peut être lancée ("&throw;") et attrapée
|
|
("&catch;") dans PHP. Le code devra être entouré
|
|
d'un bloc &try; pour faciliter la saisie d'une exception
|
|
potentielle. Chaque &try; doit avoir au moins
|
|
un bloc &catch; ou &finally; correspondant.
|
|
</para>
|
|
<para>
|
|
Si une exception est lancée et que la portée courante de la fonction n'a pas
|
|
de block &catch;, l'exception "remontera" la pile d'appel de la fonction appelante
|
|
jusqu'à trouver un bloc &catch; correspondant. Tous les blocs &finally; rencontrés
|
|
seront exécutés. Si la pile d'appel est déroulée jusqu'à la portée globale sans
|
|
rencontrer de bloc &catch; correspondant, le programme sera terminé avec
|
|
une erreur fatale sauf si un gestionnaire global d'exception a été défini.
|
|
</para>
|
|
<para>
|
|
L'objet lancé doit être une &instanceof; <interfacename>Throwable</interfacename>.
|
|
Tenter de lancer un objet qui ne l'est pas résultera en une erreur fatale émise par PHP.
|
|
</para>
|
|
<para>
|
|
À partir de PHP 8.0.0, le mot clé &throw; est une expression et peut être
|
|
utilisé dans n'importe quel contexte d'expressions. Dans les versions
|
|
antérieures c'était une déclaration qui devait être sur sa propre ligne.
|
|
</para>
|
|
|
|
<sect1 annotations="chunk:false" xml:id="language.exceptions.catch">
|
|
<title><literal>catch</literal></title>
|
|
<para>
|
|
Un bloc &catch; définit comment réagir à une exception qui a été lancée.
|
|
Un bloc &catch; définit un ou plusieurs types d'exceptions ou erreurs qu'il peut
|
|
gérer, et optionnellement une variable dans laquelle assigner l'exception.
|
|
(Cette variable était requise dans les versions antérieures à PHP 8.0.0)
|
|
Le premier bloc &catch; qu'une exception ou erreur lancée rencontre et qui correspond au
|
|
type de l'objet lancé gérera l'objet.
|
|
</para>
|
|
<para>
|
|
Plusieurs blocs &catch; peuvent être utilisés pour attraper différentes
|
|
classes d'exceptions. L'exécution normale (lorsqu'aucune exception n'est lancée
|
|
dans le bloc &try;) continue après le dernier
|
|
bloc &catch; défini dans la séquence. Les exceptions
|
|
peuvent être lancées (&throw;) ou relancées dans un bloc &catch;. Sinon,
|
|
l'exécution continuera après le bloc &catch; qui a été déclenché.
|
|
</para>
|
|
<para>
|
|
Lorsqu'une exception est lancée, le code suivant le traitement ne sera pas
|
|
exécuté et PHP tentera de trouver le premier bloc &catch; correspondant.
|
|
Si une exception n'est pas attrapée, une erreur fatale issue de PHP sera
|
|
envoyée avec un message "<literal>Uncaught Exception ...</literal>"
|
|
indiquant que l'exception n'a pu être attrapée à moins qu'un gestionnaire
|
|
d'exceptions ne soit défini avec la fonction
|
|
<function>set_exception_handler</function>.
|
|
</para>
|
|
<para>
|
|
À partir de PHP 7.1, un block &catch; peut spécifier plusieurs exceptions à
|
|
l'aide du caratère pipe (<literal>|</literal>). Ceci est utile lorsque
|
|
différentes exceptions de hiérarchies de classes différentes sont traitées
|
|
de la même manière.
|
|
</para>
|
|
<para>
|
|
À partir de PHP 8.0.0, le nom de variable pour l'exception attrapée est
|
|
optionnel. Si non spécifié, le bloc &catch; sera toujours exécuté mais
|
|
n'aura pas accès à l'objet lancé.
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 annotations="chunk:false" xml:id="language.exceptions.finally">
|
|
<title><literal>finally</literal></title>
|
|
<para>
|
|
Un bloc &finally; peut aussi être
|
|
spécifié après des blocs &catch;. Le code à l'intérieur
|
|
du bloc &finally; sera toujours exécuté après les blocs
|
|
&try; et &catch;, indépendamment du fait qu'une
|
|
exception a été lancée, avant de continuer l'exécution normale.
|
|
</para>
|
|
<para>
|
|
Une interaction notable est entre un bloc &finally; et une déclaration
|
|
&return;.
|
|
Si une déclaration &return; est rencontrée à l'intérieur des blocs &try;
|
|
ou &catch;, le bloc &finally; sera quand même exécuté. De plus,
|
|
la déclaration &return; est évaluée quand elle est rencontrée, mais le
|
|
résultat sera retourné après que le bloc &finally; soit exécuté.
|
|
Additionnellement, si le bloc &finally; contient aussi une déclaration
|
|
&return; la valeur du bloc &finally; est retournée.
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 annotations="chunk:false" xml:id="language.exceptions.exception-handler">
|
|
<title>Global exception handler</title>
|
|
<para>
|
|
Si une exception est autorisée à remonter jusqu'à la portée globale, elle peut
|
|
être attrapée par un gestionnaire d'exceptions global si il a été défini. La fonction
|
|
<function>set_exception_handler</function> peut définir une fonction qui sera
|
|
appelée à la place d'un block &catch; si aucun autre block n'est invoqué.
|
|
L'effet est essentiellement identique à entourer le programme entier dans un
|
|
block &try;-&catch; avec cette fonction en tant que &catch;.
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 annotations="chunk:false" xml:id="language.exceptions.notes">
|
|
&reftitle.notes;
|
|
|
|
<note>
|
|
<para>
|
|
Les fonctions internes de PHP utilisent principalement l'
|
|
<link linkend="ini.error-reporting">Error reporting</link>, seules les extensions
|
|
<link linkend="language.oop5">orientées objet</link>
|
|
utilisent les exceptions. Quoiqu'il en soit, des erreurs peuvent facilement être traduites en
|
|
exceptions avec <link linkend="class.errorexception">ErrorException</link>.
|
|
Cependant, cette technique ne fonctionne que pour les erreurs non fatales.
|
|
</para>
|
|
<example>
|
|
<title>Convertir l'error reporting en exceptions</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function exceptions_error_handler($severity, $message, $filename, $lineno) {
|
|
throw new ErrorException($message, 0, $severity, $filename, $lineno);
|
|
}
|
|
|
|
set_error_handler('exceptions_error_handler');
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</note>
|
|
<tip>
|
|
<para>
|
|
La <link linkend="intro.spl">bibliothèque standard PHP (SPL)</link> fournit
|
|
un bon nombre <link linkend="spl.exceptions">d'exceptions additionnelles</link>.
|
|
</para>
|
|
</tip>
|
|
</sect1>
|
|
|
|
<sect1 annotations="chunk:false" xml:id="language.exceptions.examples">
|
|
&reftitle.examples;
|
|
|
|
<example>
|
|
<title>Lancer une exception</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function inverse($x) {
|
|
if (!$x) {
|
|
throw new Exception('Division par zéro.');
|
|
}
|
|
return 1/$x;
|
|
}
|
|
|
|
try {
|
|
echo inverse(5) . "\n";
|
|
echo inverse(0) . "\n";
|
|
} catch (Exception $e) {
|
|
echo 'Exception reçue : ', $e->getMessage(), "\n";
|
|
}
|
|
|
|
// Continue execution
|
|
echo "Bonjour le monde !\n";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
0.2
|
|
Exception reçue : Division par zéro.
|
|
Bonjour le monde !
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<example>
|
|
<title>Gestion de l'exception avec un bloc &finally;</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function inverse($x) {
|
|
if (!$x) {
|
|
throw new Exception('Division par zéro.');
|
|
}
|
|
return 1/$x;
|
|
}
|
|
|
|
try {
|
|
echo inverse(5) . "\n";
|
|
} catch (Exception $e) {
|
|
echo 'Exception reçue : ', $e->getMessage(), "\n";
|
|
} finally {
|
|
echo "Première fin.\n";
|
|
}
|
|
|
|
try {
|
|
echo inverse(0) . "\n";
|
|
} catch (Exception $e) {
|
|
echo 'Exception reçue : ', $e->getMessage(), "\n";
|
|
} finally {
|
|
echo "Seconde fin.\n";
|
|
}
|
|
|
|
// On continue l'exécution
|
|
echo "Bonjour le monde !\n";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
0.2
|
|
Première fin.
|
|
Exception reçue : Division par zéro.
|
|
Seconde fin.
|
|
Bonjour le monde !
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<example>
|
|
<title>Interaction entre le bloc &finally; et &return;</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
function test() {
|
|
try {
|
|
throw new Exception('foo');
|
|
} catch (Exception $e) {
|
|
return 'catch';
|
|
} finally {
|
|
return 'finally';
|
|
}
|
|
}
|
|
|
|
echo test();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
finally
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<example>
|
|
<title>Héritage d'une exception</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class MyException extends Exception { }
|
|
|
|
class Test {
|
|
public function testing() {
|
|
try {
|
|
try {
|
|
throw new MyException('foo!');
|
|
} catch (MyException $e) {
|
|
// on la relance
|
|
throw $e;
|
|
}
|
|
} catch (Exception $e) {
|
|
var_dump($e->getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
$foo = new Test;
|
|
$foo->testing();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
string(4) "foo!"
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<example>
|
|
<title>Gestion des exceptions de capture multiple</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?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();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
string(11) "MyException"
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<example>
|
|
<title>Omettre la variable attrapé</title>
|
|
<para>Seulement permis dans PHP 8.0.0 et ultérieur.</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
function test() {
|
|
throw new SpecificException('Oopsie');
|
|
}
|
|
|
|
try {
|
|
test();
|
|
} catch (SpecificException) {
|
|
print "A SpecificException was thrown, but we don't care about the details.";
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<example>
|
|
<title>Throw en tant qu'expression</title>
|
|
<para>Seulement permis dans PHP 8.0.0 et ultérieur.</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class SpecificException extends Exception {}
|
|
|
|
function test() {
|
|
do_something_risky() or throw new Exception('It did not work');
|
|
}
|
|
|
|
try {
|
|
test();
|
|
} catch (Exception $e) {
|
|
print $e->getMessage();
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.exceptions.extending">
|
|
<title>Etendre les Exceptions</title>
|
|
<para>
|
|
Une classe d'exception définie par l'utilisateur peut être définie en étendant
|
|
la classe Exception intégrée. Les membres et les propriétés ci-dessous montrent
|
|
ce qui est accessible dans la classe enfant qui dérive de la classe Exception
|
|
intégrée.
|
|
</para>
|
|
<example>
|
|
<title>La classe d'exception intégrée</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Exception implements Throwable
|
|
{
|
|
protected $message = 'Unknown exception'; // Message d'exception
|
|
private $string; // cache de __toString
|
|
protected $code = 0; // code d'exception défini par l'utilisateur
|
|
protected $file; // nom de fichier source de l'exception
|
|
protected $line; // ligne source de l'exception
|
|
private $trace; // trace de la pile d'exécution
|
|
private $previous; // exception précédente si exception imbriquée
|
|
|
|
public function __construct($message = '', $code = 0, Throwable $previous = null);
|
|
|
|
final private function __clone(); // Inhibe la duplication des exceptions.
|
|
|
|
final public function getMessage(); // message de l'exception
|
|
final public function getCode(); // code de l'exception
|
|
final public function getFile(); // nom du fichier source
|
|
final public function getLine(); // ligne source
|
|
final public function getTrace(); // tableau de la trace de la pile d'exécution
|
|
final public function getPrevious(); // l'exception précédente
|
|
final public function getTraceAsString(); // trace sous forme de chaîne de caractères
|
|
|
|
// Peut être redéfinie
|
|
public function __toString(); // chaîne formatée pour l'affichage
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Si une classe étend la classe Exception intégrée et redéfinit le <link
|
|
linkend="language.oop5.decon">constructeur</link>, il est fortement recommandé
|
|
qu'elle appelle également <link
|
|
linkend="language.oop5.paamayim-nekudotayim">parent::__construct()</link>
|
|
pour s'assurer que toutes les données disponibles ont été correctement assignées.
|
|
La méthode <link linkend="language.oop5.magic">__toString()</link> peut être
|
|
redéfinie pour fournir une sortie personnalisée lorsque l'objet est présenté
|
|
sous forme de chaîne de caractères.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Les exceptions ne peuvent pas être clonées. Tenter de <link
|
|
linkend="language.oop5.cloning">cloner</link> une Exception entraînera une
|
|
erreur fatale <constant>E_ERROR</constant>.
|
|
</para>
|
|
</note>
|
|
<example>
|
|
<title>Étendre la classe Exception</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
/**
|
|
* Défini une classe d'exception personnalisée.
|
|
*/
|
|
class MyException extends Exception
|
|
{
|
|
// Redéfini l'exception pour que le message ne soit pas facultatif.
|
|
public function __construct($message, $code = 0, Throwable $previous = null) {
|
|
// du code
|
|
|
|
// s'assurer que tout est correctement assigné
|
|
parent::__construct($message, $code, $previous);
|
|
}
|
|
|
|
// Représentation personnalisée de l'objet sous forme de chaîne de caractères.
|
|
public function __toString() {
|
|
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
|
|
}
|
|
|
|
public function customFunction() {
|
|
echo "Une fonction personnalisée pour ce type d'exception\n";
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Créer une classe pour tester l'exception
|
|
*/
|
|
class TestException
|
|
{
|
|
public $var;
|
|
|
|
const THROW_NONE = 0;
|
|
const THROW_CUSTOM = 1;
|
|
const THROW_DEFAULT = 2;
|
|
|
|
function __construct($avalue = self::THROW_NONE) {
|
|
|
|
switch ($avalue) {
|
|
case self::THROW_CUSTOM:
|
|
// Lance une exception personnalisée
|
|
throw new MyException('1 n\'est pas un paramètre valide', 5);
|
|
break;
|
|
|
|
case self::THROW_DEFAULT:
|
|
// Lance celle par défaut.
|
|
throw new Exception('2 n\'est pas autorisé comme paramètre', 6);
|
|
break;
|
|
|
|
default:
|
|
// Aucune exception, l'object sera créé.
|
|
$this->var = $avalue;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Exemple 1
|
|
try {
|
|
$o = new TestException(TestException::THROW_CUSTOM);
|
|
} catch (MyException $e) { // Sera capturée
|
|
echo "MyException capturée\n", $e;
|
|
$e->customFunction();
|
|
} catch (Exception $e) { // Ignoré
|
|
echo "Exception par défaut capturée\n", $e;
|
|
}
|
|
|
|
// Poursuite de l'exécution
|
|
var_dump($o); // Null
|
|
echo "\n\n";
|
|
|
|
|
|
// Exemple 2
|
|
try {
|
|
$o = new TestException(TestException::THROW_DEFAULT);
|
|
} catch (MyException $e) { // Ne correspond pas à ce type
|
|
echo "MyException capturée\n", $e;
|
|
$e->customFunction();
|
|
} catch (Exception $e) { // Sera capturée
|
|
echo "Exception par défaut capturée\n", $e;
|
|
}
|
|
|
|
// Poursuite de l'exécution
|
|
var_dump($o); // Null
|
|
echo "\n\n";
|
|
|
|
|
|
// Exemple 3
|
|
try {
|
|
$o = new TestException(TestException::THROW_CUSTOM);
|
|
} catch (Exception $e) { // Sera capturée
|
|
echo "Exception par défaut capturée\n", $e;
|
|
}
|
|
|
|
// Poursuite de l'exécution
|
|
var_dump($o); // Null
|
|
echo "\n\n";
|
|
|
|
|
|
// Exemple 4
|
|
try {
|
|
$o = new TestException();
|
|
} catch (Exception $e) { // Sauté, aucune exception
|
|
echo "Exception par défaut capturée\n", $e;
|
|
}
|
|
|
|
// Poursuite de l'exécution
|
|
var_dump($o); // TestException
|
|
echo "\n\n";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|