Aller au menu - Aller au contenu

Icône Les assertions en PHP

Avatar
Mise à jour : 22/08/2008
46 visites depuis 7 jours , classé 684/777
Dans ce tuto, je vais vous présenter des petites bestioles bien utiles aux programmeurs, les assertions.

Les assertions

Une assertion est une affirmation logique définie par le développeur. Par exemple : « Le nombre de membres inscrits ne peut être négatif. ».
À l'exécution, PHP évalue toutes les assertions et renvoie une erreur si l'une d'entre elles est fausse.
Les assertions permettent donc de vérifier que des données sont cohérentes et de repérer d'éventuels comportements anormaux.

Les assertions sont une sécurité supplémentaire et ne doivent en aucun cas faire partie de votre logique de gestion ; elles ne doivent être utilisées que pour s'assurer de la validité des données.
Les assertions ne doivent pas servir à vérifier des données externes (reçues de l'utilisateur par exemple), dans ces cas-là un if() est bien plus adapté.

Je répète : les assertions ne doivent servir qu'à vérifier des données internes à un script.
Elles ne devraient pas être nécessaires au bon fonctionnement de votre application. Elles ne sont là que pour s'assurer que tout se passe bien.

Les assertions servent surtout pendant la phase de développement pour contrôler un maximum les données utilisées. C'est là leur gros avantage par rapport à une simple condition ; il devient possible de contrôler un maximum sans penser aux performances.
Effectivement, une fois que vous serez sûr(e)s du bon fonctionnement de votre application et que vous aurez besoin de performances, vous pourrez les désactiver (PHP les ignorera silencieusement et le code ne subira aucun ralentissement) ! :magicien:

C'est pour cela qu'il est conseillé d'utiliser autant que possible les assertions, même aux endroits où vous êtes sûr(e)s de votre code. Le but est de traquer les comportements anormaux. Plus vous aurez d'assertions dans votre code, plus vous aurez de chances de repérer un comportement imprévu. :)

Activons les assertions

Avant de pouvoir utiliser les assertions, il faut s'assurer qu'elles sont activées ! ;)
Par défaut, elles le sont mais on ne sait jamais. ^^
Pour activer les assertions, il existe deux méthodes.

Dans le code



Directement dans le code, via la fonction assert_options().
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php
if(assert_options(ASSERT_ACTIVE)) { // Avec comme argument la constante ASSERT_ACTIVE, assert_options renvoie TRUE si les assertions sont activées, sinon FALSE.
        echo "Les assertions sont déjà activées.";
}
else
{
        assert_options(ASSERT_ACTIVE, 1); // Avec comme argument un booléen : s'il est vrai, les assertions sont activées, sinon non.
        echo "Les assertions sont désormais activées.";
}
?>


Dans le fichier de configuration



La seconde méthode consiste à modifier le fichier de configuration de PHP, le php.ini.
Cette méthode permet à votre application d'avoir un comportement par défaut. Pendant l'analyse du code, PHP vérifie si la directive assert.active est activée. Si c'est le cas, les assertions sont utilisées, sinon elles sont ignorées.

Citation : php.ini
assert.active = On ; les assertions sont prises en compte.
assert.active = Off ; les assertions sont ignorées.


Les deux méthodes peuvent être utilisées ensemble. La directive définit un comportement par défaut mais, pour une page par exemple, vous pouvez redéfinir le comportement avec la fonction assert_options.

Utilisation d'assertions

Comment déclarer une assertion



Pour déclarer une nouvelle assertion, il faut utiliser la fonction assert(). Cette fonction prend en argument l'affirmation entre apostrophes.

Exemple :
Code : PHP
1
2
3
4
5
6
7
8
<?php
assert_options(ASSERT_ACTIVE, 1); // On active les assertions (au cas où).
 
$nombre_news = 50;
$vitesse = 100;
assert('$nombre_news >= 0'); // Le nombre de news ne peut être négatif.
assert('$vitesse > 10 && $vitesse < 150'); // La vitesse est comprise entre 10 et 150 km/h.
?>

Si vous utilisez des guillemets pour contenir votre affirmation, PHP interprète d'abord les variables contenues dedans avant de la fournir en paramètre à la fonction assert().
L'assertion assert("!empty($vitesse)") deviendrait par exemple : assert('!empty(90)'), ce qui poserait problème car empty attend une variable et non une valeur en paramètre.


Si vous testez ce code, vous allez vous rendre compte que... rien ne se passe ! o_O
Et c'est normal ! On crée une assertion disant que le nombre de news ne peut être négatif et justement, $nombre_news est positif. :D

Bon : comme ça, ça peut paraître inutile, mais il faut imaginer que la variable utilisée dans l'assertion est le résultat de calcul et n'est pas définie juste avant. ;)
Eh ! Je viens de modifier la valeur de $vitesse pour voir. Je lui ai donné 5 comme valeur et j'obtiens ça :
Warning: assert() [function.assert]: Assertion "$vitesse > 10 AND $vitesse < 150" failed in [...] on line x

C'est une erreur qui nous avertit que l'affirmation de l'assertion n'est plus vraie ($vitesse n'est plus comprise entre 10 et 150). Nous allons justement voir comment gérer les erreurs d'assertion dans la prochaine partie. :p

La gestion des erreurs



Lorsqu'une assertion n'est plus vraie, PHP renvoie une magnifique erreur de niveau E_WARNING. Nous allons voir comment personnaliser la gestion des erreurs en utilisant notre propre fonction ! :)

Personnalisations de la gestion des erreurs



Nous avons vu auparavant que la fonction assert_options() permet d'activer / désactiver les assertions. Mais cette fonction peut faire bien plus ! Une autre de ses utilisations est de définir une fonction de callback. Cette fonction spéciale sera appelée lorsqu'une assertion échouera.

Voici comment définir cette fonction :
Code : PHP
1
2
3
4
<?php
// Définition de la fonction à appeler en cas d'erreur.
assert_options(ASSERT_CALLBACK, 'nom_de_la_fonction');
?>

Il est aussi possible de définir la fonction à utiliser directement dans le php.ini avec la directive assert.callback. Si vous préférez utiliser cette méthode, pensez bien à inclure votre fonction sur chaque page utilisant les assertions.

Il ne reste plus qu'à créer votre fonction !
:o Mais comment je la crée, ma fonction de callback ?

Demandons à la doc. :magicien:
Citation : La super Doc
La fonction de callback doit accepter trois arguments. Le premier contient le nom du fichier qui a vu l'assertion échouer. Le second contient le numéro de ligne dans le fichier précédent. Le troisième argument contient l'expression qui a échoué [...].


Votre fonction doit donc accepter trois arguments :

  • le nom du fichier,
  • la ligne,
  • l'assertion qui est fausse.

Voici ce que pourrait être votre fonction :
Code : PHP
1
2
3
4
5
6
7
8
9
<?php
function gestion_assert($script, $ligne, $erreur) // Fonction qui gère les erreurs des assertions.
{
    echo "<p>Une assertion est fausse :<br />
        <strong>Script</strong> : <em>$script</em><br />
        <strong>Ligne</strong> : <em>$ligne</em><br />
        <strong>Assertion</strong> : <em>$erreur</em></p>";
}
?>

Maintenant, testons notre fonction !
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php
function gestion_assert($script, $ligne, $erreur) // Fonction qui gère les erreurs des assertions.
{
    echo "<p>Une assertion est fausse :<br />
        <strong>Script</strong> : <em>$script</em><br />
        <strong>Ligne</strong> : <em>$ligne</em><br />
        <strong>Assertion</strong> : <em>$erreur</em></p>";
}
 
 
// On active les assertions.
assert_options(ASSERT_ACTIVE, 1);
 
// Définition de la fonction à appeler en cas d'erreur.
assert_options(ASSERT_CALLBACK, 'gestion_assert');
 
// Création d'une assertion fausse.
$id_membre = -24;
assert('$id_membre >= 0');
?>

Cela marche ! C'est vrai que c'est beaucoup plus joli. :D
Ah mais attends ! J'obtiens ceci :
Citation : Ma page
Une assertion est fausse :
Script : C:\wamp\www\PHP\Dev\others\Sdz\Tuto\assertions.php
Line : 19
Assertion : $id_membre >= 0

Warning: assert() [function.assert]: Assertion "$id_membre >= 0" failed in C:\wamp\www\PHP\Dev\others\Sdz\Tuto\assertions.php on line 19


Il y a encore l'affichage d'erreur par défaut. :waw:
Pas de panique ! En fait, PHP est un peu égoïste : il ne veut pas nous laisser gérer les erreurs ! :-°
Il faut désactiver le rapport d'erreur durant l'évaluation d'une assertion. Pour faire cela, nous allons (encore !) avoir besoin de la fonction assert_options().
Il est aussi possible de définir ce comportement directement dans le php.ini en modifiant la directive assert.warning et la directive assert.quiet_eval.

Code : PHP
1
2
3
4
5
<?php
// On désactive le rapport d'erreur durant l'évaluation d'une assertion.
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);
?>

Ce qui nous donne :
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
function gestion_assert($script, $ligne, $erreur) // Fonction qui gère les erreurs des assertions.
{
    echo "<p>Une assertion est fausse :<br />
        <strong>Script</strong> : <em>$script</em><br />
        <strong>Ligne</strong> : <em>$ligne</em><br />
        <strong>Assertion</strong> : <em>$erreur</em></p>";
}
 
 
// On active les assertions.
assert_options(ASSERT_ACTIVE, 1);
 
// On désactive le rapport d'erreur durant l'évaluation d'une assertion.
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);
 
// Définition de la fonction à appeler en cas d'erreur.
assert_options(ASSERT_CALLBACK, 'gestion_assert');
 
// Création d'une assertion fausse.
$id_membre = -24;
assert('$id_membre >= 0');
?>

Et cette fois, ça fonctionne parfaitement. ;)

Petites astuces

Avoir un message explicatif lors d'une erreur



Lors d'une erreur, PHP ne fournit "que" l'assertion en cause et sa position. Il ne peut renvoyer un message expliquant pourquoi l'assertion est fausse.
Pour faire cela, il existe une astuce permettant d'afficher des messages d'erreurs personnalisés. Cette astuce consiste à ajouter un commentaire dans l'affirmation. À l'affichage de l'assertion qui est fausse, le commentaire peut être utilisé comme un message explicatif.
Si l'on reprend le code d'avant en utilisant cette astuce, cela donne :
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
function gestion_assert($script, $ligne, $erreur) // Fonction qui gère les erreurs des assertions.
{
        $array = explode("//", $erreur); // On récupère le commentaire qui va faire office de message explicatif.
        list($erreur, $explication) = $array;
        echo "<p>Une assertion est fausse :<br />
       <strong>Script</strong> : <em>$script</em><br />
       <strong>Ligne</strong> : <em>$ligne</em><br />
       <strong>Assertion</strong> : <em>$erreur</em><br />
       <strong>Cause</strong> : <em>$explication</em></p>";
}
 
 
// On active les assertions.
assert_options(ASSERT_ACTIVE, 1);
 
// On désactive le rapport d'erreur durant l'évaluation d'une assertion.
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);
 
// Définition de la fonction à appeler en cas d'erreur.
assert_options(ASSERT_CALLBACK, 'gestion_assert');
 
// Création d'une assertion fausse.
$nombre_pages = -24;
assert('$nombre_pages >= 0; //Le nombre de page est négatif');
?>

Si vous ajoutez un commentaire dans l'assertion, vous devez impérativement mettre un ; entre l'affirmation et le commentaire.


Arrêter l'exécution du script en cas d'erreur



Par défaut, les erreurs d'assertion ont un niveau de type : E_WARNING.
Ce type d'erreur n'arrête pas l'exécution du code. Si vous voulez que les erreurs d'assertion aient un niveau plus élevé, l'exécution s'arrêtera donc en cas d'assertion fausse, vous devez utiliser la fonction assert_options() et la directive ASSERT_BAIL.
Modifiable directement dans le php.ini : directive assert.bail.

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?php
// On active les assertions.
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_BAIL, 0); // 0 -> continue l'exécution même en cas d'erreur | 1-> arrête l'exécution en cas d'erreur .
 
// Création d'une assertion fausse.
$id_membre = -24;
assert('$id_membre >= 0');
 
echo "Les assertions c'est bien !"; // Message affiché.
?>
C'est la fin de ce tuto. Si vous avez des questions / critiques ou toute autre chose à dire : n'hésitez pas !
Merci à Tortue Facile, à Dentuk et aux zcorrecteurs (surtout ptipilou) pour leurs conseils, corrections et relectures. :)

f

Partager

24 commentaires pour "Les assertions en PHP"
Note moyenne : 3.80 / 4 (5 votes)
Pseudo Commentaire
Hors ligne Sowhat # Posté le 12/03/2008 à 02:57:26
Redlime >3
Avatar

Merci à vous :]
Le tuto a été corrigé par les zcorrecteurs, merci à eux !
Hors ligne matheod # Posté le 16/05/2008 à 18:18:52

Avatar

Super !

19 !

Une question : y a til une fonction générale à faire pour faire executer une fonction lors d'une erreur (n'importe quel erreur, pas une erreur d'assertion) ?
merci

Un jeux original qui change des mmorpg tout en en gardant le thème : League Of legend!

Un contrôle parentale sur le site du zero pour les admins ?
Image utilisateur
 
Hors ligne valval14 # Posté le 24/11/2009 à 23:50:58
Avatar

Merci pour ce tuto, ça m'a motivé pour utiliser les assertions, en PHP et en Java. :)

J'ai juste une question (même si d'après ce que j'ai compris de la doc c'est sans doute pas possible :lol: ) :

Est-il possible de passer d'autres arguments à la méthode gestion_assert() ?


J'aurais aimé par exemple ajouter un booléen pour afficher le message d'erreur personnalisé soit en français soit en anglais.

si une telle chose est possible ça serait intéressant de l'indiquer dans le tuto.
Hors ligne softdounia # Posté le 13/05/2010 à 10:54:07
A
Avatar

Ville : Alger
Pays : Algérie
Études : USTHB

Hi, les tests fonctionnel avec PhpUnit... (Ma contribution a ce tuto)

à la fin du mini tuto tu trouvera ce que tu cherche:
http://www.unixgarden.com/index.php/programmation/phpunit -tests-unitaires-pour-php

Cordialement
SoftDounia

Les 40e rugissants et les 50e hurlants. o_O --> Brainstorming --> CamelCase
Image utilisateur

-------------
"je crois qu'on ne peut mieux vivre qu'en chercant à devenir meilleur, ni plus agréablement qu'en ayant pleine conscience de son amélioration"
Socrate >_<
-------------
les meilleurs peintres se sont fait dire qu’ils n’étaient pas bon, aujourd’hui ce sont des Dieux!
-------------
RTFM :-° l'expression anglaise d'argot Internet Read the fucking manual (« Lis le foutu manuel ») ;
-------------
Mon CV en ligne ici
 
Hors ligne Sannazzarotiti # Posté le 17/06/2011 à 10:30:21
Avatar

Ville : Nantes
Pays : France métropolitaine

J’étais vraiment content de découvrir sa (même si j'ai lu en diagonale pour le moment). Je vais donc sur la doc pour me renseigner et voila ce que je lis :

Citation
Il est recommandé de n'utiliser les assertions que comme outil de déboguage. Vous pouvez les utiliser pour les vérifications d'usage : ces conditions doivent normalement être vraies, et indiquer une erreur de programmation si ce n'est pas le cas. Vous pouvez aussi vérifier la présence de certaines extensions ou limitations du système.


J'avais aussi peur que sa soit lent mais apparemment ce n'est pas le cas.

Voir tous les commentaires
Ce tutoriel a été corrigé par les zCorrecteurs.