Les procédures et fonctions utilisateurs

Rechercher

Les procédures et fonctions utilisateurs

  • Par Emacs
  • 7 commentaires
  • 29524 lectures
  • RSS -  Atom

Comme dans la plupart des langages de programmation, il est possible en PHP de créer ses propres fonctions qui viennent compléter les fonctions natives. Cela permet de remplir des opérations particulières qui sont redondantes dans l'application, et de résoudre un problème en le fragmentant en plusieurs petits problèmes et solutions.

Ce tutoriel présente les fonctions utilisateurs. Nous définirons tout d'abord ce qu'est une fonction et une procédure. Puis nous verrons comment déclarer une fonction et lui demander de renvoyer une ou plusieurs valeurs, avant d'aborder les principes de visibilité et de portée de variables. Enfin nous expliquerons les mécanismes de passage de paramètres (par copie et par référence) et terminerons par les fonctions à arguments infinis.

Qu'est-ce qu'une fonction / procédure utilisateur ?

En plus des fonctions natives qui ne nécessitent pas d'importation de bibliothèque avant leur appel, il existe les fonctions utilisateurs. Celles-ci sont créées par le programmeur lui même et enregistrées dans une librairie externe.

Plus concrètement, une fonction utilisateur se définit comme une suite d'instructions plus ou moins longue et complexe. Cette fonction peut-être perçue comme un sous-programme du programme principal qui l'appelle.

Il existe deux types de fonctions utilisateurs : les fonctions et les procédures. Quelle différence y-a-t-il entre les deux ? La différence qui les sépare est la valeur de retour. Une procédure est un groupe d'instructions qui ne renvoie pas de valeur après leur exécution. Une fonction, quant à elle, est en réalité une procédure qui retourne une valeur (de type primitif ou complexe) ou un objet.

Enfin, une fonction utilisateur peut (ou non) prendre des paramètres d'entrée au même titre qu'une fonction mathématique. Ces paramètres peuvent être de type primitif (int, float, string, boolean) ou structuré (array, object).

Déclaration d'une fonction

Principe de base

Une fonction utilisateur est définie par deux principaux éléments. Sa signature et son corps. La signature est elle même composée de deux parties : le nom et la liste de paramètres. Le corps, quant à lui, établit la suite d'instructions qui devront être exécutées.

La déclaration d'une nouvelle fonction se réalise au moyen du mot-clé function suivi du nom de la fonction et de ses arguments. Le code suivant illustre tout ça :

Exemple de déclaration d'une fonction
<?php
function nomDeLaFonction($param1, $param2, ...)
{
// Bloc d'instructions
}
?>

Lors de la déclaration d'une fonction, son nom et le nom de ses paramètres sont totalement arbitraires. Il est possible de nommer la fonction et ses arguments dans un langage naturel. Exemple : parcourirLeTableau($tableau).

Attention : une fonction ne doit être déclarée qu'une seule fois. Dans le cas contraire, un message d'erreur sera retourné par l'interprêteur PHP.

Prenons un exemple très simple d'une fonction (procédure en réalité) qui calcule la somme des deux paramètres. Le résultat est stocké dans une variable locale $somme puis affiché au moyen d'une instruction echo().

Déclaration d'une procédure
<?php
function calculerSomme($a, $b)
{
// Déclaration de la variable locale $somme
$somme = $a + $b;
// Affichage du résultat
echo 'La somme de ', $a ,' et de ', $b ,' vaut ', $somme;
}
?>

Valeur par défaut

Il est possible d'appliquer une valeur par défaut à un paramètre si celui-ci n'est pas indiqué lors de l'appel. Dans notre exemple précédent nous allons appliquer la valeur 5 par défaut au paramètre $b.

Affectation d'une valeur par défaut à un paramètre
<?php
function calculerSomme($a, $b=5)
{
// Déclaration de la variable locale $somme
$somme = $a + $b;
// Affichage du résultat
echo 'La somme de ', $a ,' et de ', $b ,' vaut ', $somme;
}
?>

Valeur de retour

Comme nous l'avions expliqué plus haut, il y'a deux sortes de fonctions utilisateurs : les fonctions et les procédures. Jusque là, notre exemple était une procédure puisqu'il ne renvoyait aucune valeur (soit void). Nous allons à présent modifier notre fonction pour qu'elle renvoie la somme des deux paramètres au lieu de l'afficher sur la sortie standard.

Déclaration d'une fonction
<?php
function calculerSomme($a, $b)
{
// Déclaration de la variable locale $somme
$somme = $a + $b;
// Renvoi de la somme au programme principal
return $somme;
}
?>

Nous remarquons ici la présence d'un nouveau mot clé. Il s'agit de return. L'instruction return renvoie la valeur de la variable locale $somme au programme principal qui appelle la fonction. Nous verrons dans la partie suivante comment récupérer cette valeur. L'exécution de la fonction est stoppée immédiatement après l'exécution de cette instruction return.

Une fonction peut aussi comporter plusieurs instructions return dans son corps. Voici un exemple qui simule un mécanisme vérifiant qu'une personne est connectée.

Exemple d'une fonction ayant plusieurs instructions return
<?php
function estConnecte($connecte)
{
// Test du paramètre d'entrée
if(1 === $connecte)
{
return true;
}
return false;
}
?>

Ici nous renvoyons une valeur booléenne (true ou false) en fonction de l'état de la variable $connecte.

Important : une fonction ne peut retourner qu'une seule et unique valeur de type primitif à la fois. Pour renvoyer plusieurs valeurs d'un coup, il faut avoir recours au tableau. Le principe est expliqué juste après.

Retour de plusieurs valeurs

Dans certains cas particuliers d'applications il est demandé à une fonction de retourner plusieurs valeurs d'un coup. Nous avons vu précédemment que l'appel de plusieurs instructions return était impossible. Pour palier à cette faiblesse, le langage PHP autorise le renvoi d'un tableau de valeurs, soit un type structuré.

Prenons l'exemple d'une fonction qui renvoie les identifiants de connexion à une base de données. Ceci est un exemple totalement arbitraire.

Exemple de renvoi d'un tableau
<?php
function getIdentifiantsSql()
{
return array('sql.monsite.com','monLogin','monPassword','maBaseDeDonnees');
}
?>

Nous aurions pu aussi d'abord déclarer le tableau local et lui affecter les valeurs avant de le retourner comme le montre le code suivant.

Déclaration puis renvoi du tableau
<?php
function getIdentifiantsSql()
{
$arrayIdentifiants = array();
$arrayIdentifiants[] = 'sql.monsite.com';
$arrayIdentifiants[] = 'monLogin';
$arrayIdentifiants[] = 'monPassword';
$arrayIdentifiants[] = 'maBaseDeDonnees';
return $arrayIdentifiants;
}
?>

Appel d'une fonction

Jusqu'à maintenant nous déclarions des fonctions mais nous ne les utilisions pas. C'est ce que nous allons étudier maintenant avec l'appel de fonction.

L'appel d'une fonction se fait dans le programme principal après avoir déclarer la fonction. Une fonction est appellée grâce à son nom suivi des paramètres. Reprenons notre toute première fonction qui calcule la somme de deux nombres et affiche le résultat sur la sortie standard. L'appel se réalise de la manière suivante :

Appel de la procédure calculerSomme()
<?php
/**
* Ici la fonction a été déclarée
*/
/**
* Appel de la procédure
*/
calculerSomme(10,1);
echo '<br/>';
calculerSomme(7, 23);
echo '<br/>';
calculerSomme(130, 231);
echo '<br/>';
calculerSomme(98, 62);
echo '<br/>';
?>

Après exécution des 4 fonctions, le résultat produit est le suivant :

Résultat de l'exécution des appels à calculerSomme()
La somme de 10 et de 1 vaut 11
La somme de 7 et de 23 vaut 30
La somme de 130 et de 231 vaut 361
La somme de 98 et de 62 vaut 160

Voyons maintenant ce que cela donne avec la même fonction qui renvoie la valeur. Celle dotée de l'instruction return. En exécutant le code précédent, nous remarquons que rien ne s'affiche alors que l'exécution s'est déroulée comme prévue. Pourquoi ? Tout simplement parceque les valeurs retournées n'ont pas été récupérées et stockées dans des structures de données (variables, tableau, objet...). Nous allons donc les stocker dans un tableau nommé $resultatsSomme avant d'afficher le contenu de celui-ci.

Exemple de récupération de valeur retournée par la fonction calculerSomme()
<?php
/**
* Ici la fonction a été déclarée
*/
// Déclaration du tableau
$resultatsSomme = array();
/**
* Appel de la fonction
*/
$resultatsSomme[] = calculerSomme(10,1);
$resultatsSomme[] = calculerSomme(7, 23);
$resultatsSomme[] = calculerSomme(130, 231);
$resultatsSomme[] = calculerSomme(98, 62);
// Affichage du contenu du tableau
echo '<pre>';
print_r($resultatsSomme);
echo '</pre>';
?>

Ce qui produit le résultat suivant :

Résultat de l'exécution du script
Array
(
[0] => 11
[1] => 30
[2] => 361
[3] => 160
)

Il faut donc toujours penser à enregistrer la / les valeurs de retour dans une variable / tableau, ou bien l'utiliser directement dans une condition.

Visibilité des variables

Lorsqu'une variable est déclarée, sa visibilité dans le programme principal dépend de son contexte. En PHP il existe 3 niveaux de visibilité décrits ci-dessous :

  • Les variables superglobales : ce sont en fait les tableaux tels que $_SESSION, $_COOKIE, $_GET, $_POST, $_SERVER... Il sont créés directement par PHP et sont accessibles (en lecture et écriture) depuis n'importe où dans le programme. Ils peuvent donc être appelés à l'intérieur d'une fonction sans être passés en paramètre de celle-ci.
  • Les variables globales : ce sont toutes les variables, tableaux, objets et constantes que nous créons nous-même dans le programme principal. Ces structures de données ne sont visibles en théorie que dans le programme principal mais il est possible d'y avoir accès dans une fonction sans les passer en paramètre. Nous verrons cela plus loin dans ce cours.
  • Les variables locales : ce sont toutes les variables d'une fonction (paramètres compris). Leur visibilité n'est que locale, c'est à dire dans la fonction elle-même. Le programme principal ne peut donc pas agir sur ces variables. C'est aussi d'ailleurs pourquoi leur nom peut-être totalement choisi arbitrairement sans risque de confusion pour PHP avec les variables globales du programme principal. Elles sont automatiquement supprimées de la mémoire lorsque la fonction a été complètement executée.

Si nous tentons d'appeler une variable qui ne se trouve pas dans le bon contexte, l'interprêteur PHP retournera une erreur de type Notice: Undefined variable: monNom in /Applications/MAMP/htdocs/Tests-PHP/fichier.php on line 8

Portée d'une variable

Nous venons de voir que les variables déclarées globales dans le programme principal et les variables locales déclarées à l'intérieur d'une fonction ne peuvent être accessibles. Les deux espaces étant complètement fermés et indépendants. En PHP il existe 3 niveaux de portée d'une variable qui sont global, local et statique. Le dernier est un peu particulier.

  • Une variable déclarée dans la fonction et préfixée par le mot-clé global est considérée comme globale. Elle devient alors visible dans la fonction mais aussi à l'extérieur de celle-ci.
  • Une variable déclarée traditionnellement dans la fonction prend par défaut une portée locale. Elle est alors visible uniquement dans la fonction et est détruite à la fin de son exécution.
  • Une variable déclarée dans la fonction et préfixée par le mot-clé static est considérée comme une variable locale dont la valeur se conserve tout au long de l' exécution du programme principal. Cette valeur pourra alors être réutilisée en appelant la fonction de nouvelles fois.

Illustrons le premier et le troisième points à l'aide d'un exemple commun. La fonction suivante simule le remplissage d'une voiture en carburant. Le budget en carburant est une variable globale décrémentée du montant du plein d'essence.

Exemple d'illustration de la portée des variables dans une fonction
<?php
// Déclaration de la fonction
function remplirReservoir($volume, $prixAuLitre)
{
// Déclaration des variables
global $budgetEssence;
static $volumeTotalEssence;
$montant = 0;
// Calcul du prix du remplissage de l'essence
$montant = round($volume * $prixAuLitre, 2);
// Retrait de $montant à $budgetEssence
$budgetEssence -= $montant;
// Ajout du volume au volume total enregistré
$volumeTotalEssence += $volume;
// Affichage des informations
echo 'Vous avez mis ', $volume ,'L d\'essence.';
echo 'Prix au Litre : ', $prixAuLitre ,' euros.</br>';
echo 'Prix total : ', $montant ,' euros.';
echo 'Budget essence restant : ', $budgetEssence ,' euros.';
echo 'Volume total d\'essence depuis le début : ', $volumeTotalEssence ,'L.';
}
// Déclaration des variables globales
$budgetEssence = 700;
// Premier plein d'essence
remplirReservoir(42, 1.25);
// Second plein d'essence
remplirReservoir(38, 1.19);
// Troisième plein d'essence
remplirReservoir(43, 1.23);
?>

Le resultat après exécution du programme est le suivant :

Résultat de l'exécution du programme
Vous avez mis 42L d'essence.
Prix au Litre : 1.25 euros.
Prix total : 52.5 euros.
Budget essence restant : 647.5 euros.
Volume total d'essence depuis le début : 42L.
Vous avez mis 38L d'essence.
Prix au Litre : 1.19 euros.
Prix total : 45.22 euros.
Budget essence restant : 602.28 euros.
Volume total d'essence depuis le début : 80L.
Vous avez mis 43L d'essence.
Prix au Litre : 1.23 euros.
Prix total : 52.89 euros.
Budget essence restant : 549.39 euros.
Volume total d'essence depuis le début : 123L.

Explications : la variable $budgetEssence est déclarée globale dans la fonction. Cela signifie qu'elle est accessible en lecture et écriture dans la fonction mais aussi à l'extérieur de celle-ci. La variable $volumeTotalEssence est déclarée statique. La variable $montant est une variable locale utile uniquement pendant l'exécution de la fonction. Elle est détruite lorsque la fonction est complètement exécutée. Elle compte le volume total d'essence acheté depuis le début. Sa valeur est donc conservée pour les appels suivants de la fonction. La fonction native round() arrondit la somme du plein d'essence à deux chiffres après la virgule. L'étape de calcul suivante utilise les opérateurs combinés arithmétiques. Plus d'informations sur le tutoriel des opérateurs de PHP.

Passage de paramètre par copie ou référence

Nous entamons l'avant dernier point important concernant les fonctions utilisateurs. Il s'agit du passage de paramètres (que nous avons déjà vu lors des appels de fonctions). Il existe deux types de passage de paramètres en PHP. Il s'agit du passage par copie ou bien le passage par référence.

Dans le premier cas, la valeur passée en paramètre de la fonction n'est pas modifiée. En réalité la fonction travaille sur une copie de cette valeur. C'est aussi le passage de paramètre par défaut de PHP. Voici un exemple simple qui présente le mécanisme :

Présentation du mécanisme de passage par valeur
<?php
function multiplierParDeux($nombre)
{
$nombre *= 2;
}
$unNombre = 5;
multiplierParDeux($unNombre);
echo $unNombre; // Affiche 5
?>

Pour pouvoir modifier la valeur de $unNombre, il faut procéder à un passage par référence. Le passage par référence consiste à passer l'adresse mémoire de la variable et non une copie de sa valeur. Pour cela, il faut simplement ajouter le symbole & devant le paramètre dans la signature de la fonction. Reprenons notre exemple précédent :

Présentation du mécanisme de passage par référence
<?php
function multiplierParDeux(&$nombre)
{
$nombre *= 2;
}
$unNombre = 5;
multiplierParDeux($unNombre);
echo $unNombre; // Affiche 10
?>

Note : les objets sont toujours passés par référence. Le passage par copie ne s'applique pas à ces structures de données.

Il est également possible de retourner des valeurs par référence mais cela n'a pas grand intérêt puisqu'en général nous renvoyons la valeur d'une variable locale que nous stockons ensuite dans une variable globale du programme principal. Dans certains cas très particuliers, cela peut se révéler intéressant. Pour signaler le retour par référence d'une valeur, nous devons placer le symbole & devant le nom de la fonction lors de sa déclaration.

Les fonctions à paramètres infinis

PHP permet également de créer des fonctions à paramètres infinis. C'est ce que l'exemple suivant illustre.

Exemple de déclaration et d'appel de fonction à paramètres infinis
<?php
function avoirPortraitRobot()
{
// Stockage des paramètres dans un tableau
$infosPortrait = func_get_args();
// Affichage des informations
echo 'Le portrait robot du suspect a ', func_num_args() ,' critères :';
foreach($infosPortrait as $element)
{
echo ' - ', $element ,'';
}
}
avoirPortraitRobot
(
'homme',
'yeux bleux',
'brun',
'cheveux coupés courts',
'1m85',
'nez crochu',
'balafré à la joue gauche'
);
?>

Notons que nous déclarons une fonction sans paramètre. Le résultat de l'exécution du code précédent est le suivant :

Résultat de l'exécution du programme
Le portrait robot du suspect a 7 critères :
homme
yeux bleux
brun
cheveux coupés courts
1m85
nez crochu
balafré à la joue gauche

Conclusion

Nous avons maintenant fait le tour de ce que l'on peut dire à propos des fonctions utilisateurs. Nous avons tout d'abord défini ce qu'est une fonction et une procédure. Puis nous avons montré comment la déclarer et lui faire retourner une ou plusieurs valeurs. Nous nous sommes ensuite attardés sur le principe d'appel de procédure avant d'expliquer les principes de visibilité et de portée d'une variable. Enfin nous avons étudié les types de passages de paramètres et le retour de valeur (par copie ou par référence) avant de terminer par les fonctions à arguments infinis.



Les commentaires

1. Par kameleon le 07/05/2008 06:20

juste une petite remarque qui n'a rien avoir avec le php.
on écris en appelant et pas en appellant(dans la portée des variables

2. Par kameleon le 07/05/2008 08:36

dans l'exemple d'illustration de la portée des variables dans une fonction, il faut déspécialiser:
echo 'Vous avez mis ', $volume ,'L d'essence.'; comme suit:
echo 'Vous avez mis ', $volume ,'L d\'essence.';

3. Par Emacs le 07/05/2008 13:04

Merci Kaméléon, c'est corrigé

4. Par iMac le 05/12/2008 15:22

Il me semble qu'il y a une inversion de phrase dans les explications sur la portée des variables, cf : $volumeTotalEssence.

5. Par shivato le 25/04/2009 09:55

Je ne pense pas que l'on puisse faire de la concaténation avec des virgules ??

echo 'Le portrait robot du suspect a ', func_num_args() ,' critères :';

6. Par Emacs le 25/04/2009 11:33

@shivato : il ne s'agit pas de concaténation. echo() n'est pas véritablement une fonction mais une structure du langage qui peut prendre une infinité de paramètres. Dans l'exemple de ce tutorial, echo() prend 3 paramètres, tous séparés par une virgule.

7. Par sophie_et_cie le 29/06/2009 14:17

MERCI pour ces tutoriaux clairs et très agréables à lire et à suivre !
P.S. : Comme le disait iMac en décembre, dans le paragraphe sur l'explication des variables globales et statiques du programme "budget en carburant", 2 phrases ne semnblent pas au bon endroit...