Dans la plupart des cas, sans paramètres et arguments les fonctions ne serviraient pas à grand chose. Nous allons voir comment définir ces paramètres, leur donner des valeurs par défaut, ou réaliser des fonctions avec un nombre variable de paramètres.

### Pas de déclaration de type

Dans le premier exemple que nous avons vu, la fonction afficher acceptait 3 paramètres : $texte , $titre et $coul.

    function afficher($texte, $titre, $coul) {
      echo '<h3 style="background:', $coul, '">';
      echo $titre;
      echo '</h3>';
      echo '<p>', $texte, '</p>';
    }

Comme PHP est un langage à typage dynamique, on ne précise pas le type du paramètre attendu.

N'importe quel type de données peut être passé comme paramètre à une fonction : tout type scalaire (nombre, chaîne et booléen), tout type composé (tableau et objet), tout type spécial (ressource et null).

Dans l'exemple suivant la fonction afficher est modifiée pour qu'elle fonctionne avec le paramètre $coul qui soit une chaîne de caractères ou un nombre.

Exemple : paramètres
<!DOCTYPE html> <html lang="fr"> <head><title>Test fonction</title></head> <body> <?php function afficher($texte, $titre, $coul) { if (is_numeric($coul)) { $coul = '#'.dechex($coul); } echo '<h3 style="background:', $coul, '">'; echo $titre; echo '</h3>'; echo '<p>', $texte, '</p>'; } $txt = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; afficher($txt, 'Introduction', 16776960); $txt = 'Phasellus vel erat eu elit mattis lobortis non elementum risus.'; afficher($txt, 'Développement', '#FFFF00'); ?> </body> </html>

Le paramètre passé peut être la valeur d'une variable, une expression littérale ou la valeur de l'évaluation d'une expression.

Dans :

    afficher($txt, 'Introduction', 16776960);

$txt est une variable, 'Introduction' et 16776960 sont des expressions littérales.

On pourrait aussi utiliser le résultat d'une expression comme par exemple :

    afficher($txt, strtoupper('Introduction'), 16776000 + 960);

Exemple : paramètres
<!DOCTYPE html> <html lang="fr"> <head><title>Test fonction</title></head> <body> <?php function afficher($texte, $titre, $coul) { if (is_numeric($coul)) { $coul = '#'.dechex($coul); } echo '<h3 style="background:', $coul, '">'; echo $titre; echo '</h3>'; echo '<p>', $texte, '</p>'; } $txt = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; afficher($txt, strtoupper('Introduction'), 16776000 + 960); ?> </body> </html>

Depuis PHP 7, si on tente d'appeler une fonction avec un nombre insuffisant de paramètres, une erreur fatale arrête le script.

Exemple : paramètres
<!DOCTYPE html> <html lang="fr"> <head><title>Test fonction</title></head> <body> <?php function afficher($texte, $titre, $coul) { if (is_numeric($coul)) { $coul = '#'.dechex($coul); } echo '<h3 style="background:', $coul, '">'; echo $titre; echo '</h3>'; echo '<p>', $texte, '</p>'; } $txt = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; afficher($txt, 'Introduction', 16776000); afficher($txt, 'Erreur fatale'); //=> erreur fatale // qui arrête le script afficher($txt, 'pas exécuté', 16776000); ?> </body> </html>

### Arguments avec valeur par défaut

Nous pouvons définir des arguments avec des valeurs par défaut en utilisant la syntaxe $param = valeur_par_défaut.
valeur_par_défaut doit obligatoirement être une constante, et ne peut être ni une variable, ni un membre de classe, ni un appel de fonction. PHP vous autorise à utiliser des tableau ainsi que le type spécial NULL comme valeur par défaut.

Quand nous appelons une telle fonction, si nous voulons utiliser ses valeurs par défaut, il suffit de ne pas donner de valeur correspondant au paramètre.

Pour mettre une couleur par défaut dans notre fonction afficher, on modifie sa déclaration :

    function afficher($texte, $titre, $coul = '#FFFF00') {
    ...
    }

et son appel :

    afficher($txt, 'Introduction');

en omettant le 3éme paramètre.

Exemple : arguments avec valeur par défaut
<!DOCTYPE html> <html lang="fr"> <head><title>arguments avec valeur par défaut</title></head> <body> <?php function afficher($texte, $titre, $coul = '#FFFF00') { if (is_numeric($coul)) { $coul = '#'.dechex($coul); } echo '<h3 style="background:', $coul, '">'; echo $titre; echo '</h3>'; echo '<p>', $texte, '</p>'; } $txt = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; afficher($txt, 'Introduction'); $txt = 'Phasellus vel erat eu elit mattis lobortis non elementum risus.'; afficher($txt, 'Développement', '#FF0000'); ?> </body> </html>

Si vous utilisez des arguments avec valeur par défaut avec d'autres sans valeur par défaut, les premiers doivent être placés à la suite de tous les arguments sans valeur par défaut. Sinon, cela ne fonctionnera pas.

### Passage d'arguments par valeur

Argument est le nom donné au paramètre quand il est utilisé à l'intérieur de la fonction.

Dans la majorité des cas, les paramètres transmis à une fonction le sont par valeur : le paramètre utilisé lors de l'appel de la fonction est évalué et la valeur résultante est assignée à l'argument correspondant dans la fonction. Une copie de la valeur est faite en mémoire. Si nous changeons la valeur de l'argument dans la fonction, cela ne change pas la valeur du paramètre correspondant à l'extérieur de la fonction.

Le passage d'argument par valeur est la méthode par défaut utilisée par PHP.

### Passage d'arguments par référence

Quand on passe un argument par référence, on passe l'adresse mémoire du paramètre. Aucune copie de la valeur n'est faite. Si la fonction modifie la valeur de l'argument, la valeur du paramètre correspondant à l'extérieur de la fonction sera automatiquement modifiée puisque les 2 éléments pointent sur la même adresse mémoire.
D'une certaine façon, le passage d'arguments par référence permet de dépasser la portée des variables.

Quand le nom de l'argument est précédé du caractère & (ampersand) dans l'entête de la fonction, il est passé par référence :

    function une_fonction(&$par_ref, $par_val) { ...

Le passage d'argument par référence est intéressant dans le cas de variables de grandes tailles (chaînes de caractères, tableaux, etc).

Le passage d'arguments par référence est uniquement possible avec des variables.

    une_fonction(&'abcd', &1234);

provoquera une erreur.
Exemple 1 : passage d'un scalaire par valeur/référence
<!DOCTYPE html> <html lang="fr"> <head> <title>passage d'un scalaire par valeur/référence</title> </head> <body> <?php function f1 ($par_val){ ++$par_val; } function f2 (&$par_ref){ ++$par_ref; } $a = 1; f1($a); echo '<hr>', $a; $b = 1; f2($b); echo '<hr>', $b; ?> </body> </html>
Exemple 2 : passage d'un tableau par valeur/référence
<!DOCTYPE html> <html lang="fr"> <head> <title>passage d'un tableau par valeur/référence</title> </head> <body> <?php function f1 ($ar_val){ ++$ar_val[0]; } function f2 (&$ar_ref){ ++$ar_ref[1]; } $a = array(10, 10); f1($a); echo '<hr>'; var_dump($a); $b = $a; //$b reçoit une copie de $a f2($b); echo '<hr>'; var_dump($a); var_dump($b); ?> </body> </html>
Le cas des objets est traité dans le chapitre qui leur est consacré.

### Nombre variable de paramètres

Avec PHP, les fonctions peuvent avoir un nombre variable de paramètres. Pour définir une telle fonction, il suffit de ne pas donner de paramètres dans la déclaration de la fonction :

    function parametres_variables() {
    	...
    }

PHP fournit trois fonctions qui donnent des informations sur les paramètres passés à une fonction :

- func_get_args retourne les arguments d'une fonction sous forme de tableau
- func_get_arg retourne un élément de la liste des arguments
- func_num_args retourne le nombre d'arguments passés à la fonction.

Exemple : nombre variable de paramètres
<!DOCTYPE html> <html lang="fr"> <head><title>Nombre variable de paramètres</title></head> <body> <?php function additionner() { // Exemple avec utilisation d'une boucle foreach // et de la function func_get_args pour récupérer // la valeur des arguments $somme = 0; $args = func_get_args(); foreach ($args as $nombre) { $somme += $nombre; } echo '<hr>Somme = ', $somme, '<hr>'; } //------------------------------------------------------ additionner(1, 2, 3, 4); additionner(12, 34, 56, 78, 910, 1112); ?> </body> </html>
Exemple : nombre variable de paramètres
<!DOCTYPE html> <html lang="fr"> <head><title>Nombre variable de paramètres</title></head> <body> <?php function additionner() { // Exemple avec utilisation d'une boucle for // et de la function func_get_arg pour récupérer // la valeur des arguments $somme = 0; $nbArg = func_num_args(); for ($i = 0; $i < $nbArg; $i++) { $somme += func_get_arg($i); } echo '<hr>Somme = ', $somme, '<hr>'; } //------------------------------------------------------ additionner(1, 2, 3, 4); additionner(12, 34, 56, 78, 910, 1112); ?> </body> </html>
Le code de la fonction

      $somme = 0;
      $nbArg = func_num_args();

      for ($i = 0; $i < $nbArg; $i++) {
        $somme += func_get_arg($i);
      }

pourrait être remplacé par une boucle for sans bloc de code :

      for ($i = $somme = 0, $nbArg = func_num_args();
      		$i < $nbArg;
      		$somme += func_get_arg($i++));

Pour moi, la lisibilité et la compréhension du code en est affectée.

### Exercice : fonction calculer

En utilisant le principe du nombre variable de paramètre, écrivez la fonction calculer qui donne comme résultat la multiplication ou l'addition des éléments qui lui sont passés en paramètre. Il est convenu que le premier paramètre passé défini l'opération à faire.

Une solution possible

Exercice : fonction calculer
<!DOCTYPE html> <html lang="fr"> <head> <title>Calculer</title> </head> <body> <?php function calculer() { $nbArg = func_num_args(); $resultat = func_get_arg(1); if (func_get_arg(0) == '+') { for ($i = 2; $i < $nbArg; $i++) { $resultat += func_get_arg($i); } } elseif (func_get_arg(0) == '*') { for ($i = 2; $i < $nbArg; $i++) { $resultat *= func_get_arg($i); } } echo '<hr>Résultat = ', $resultat, '<hr>'; } calculer('+', 1, 2 ,3, 4); calculer('*', 1, 2, 3, 4); ?> </body> </html>