T: / Articles techniques / PHP
Les fonctions sont des outils réutilisables qui vont exécuter un ensemble d’instructions plus ou moins complexes.
On continue l’apprentissage de PHP avec un nouvel élément clé de la programmation et de l’algorithmie : les fonctions. Il faut voir les fonctions comme des outils qui vont réaliser directement un ou plusieurs instructions plus ou moins complexes.
Il y a des fonctions dites « natives », qui font de base partie de PHP. echo est une fonction par exemple.
Et il y a les fonctions que l’on peut construire soi même pour les réutiliser dans son code.
Au programme :
PHP propose de base un très grand nombre de fonctions natives. C’est à dire que le langage a de base un ensemble d’outils que l’on peut utiliser directement et qui facilitent ou accélèrent le développement
Ces fonctions natives permettent plein de choses :
La liste est longue et il y a actuellement + de 1000 fonctions natives en PHP ! Et de nouvelles arrivent à chaque nouvelle version du langage.
Etant donné ce volume, il est impossible de toutes les connaitre. Heureusement, elles sont toutes bien documentées sur la documentation officielle de PHP : php.net.
On va voir un peu comment les fonctions sont présentées dans la documentation avec l’exemple de la fonction strlen qui permet de récupérer la longueur d’une chaine de caractères : strlen
Voici la liste des éléments principaux de la documentation et qui vont permettre de comprendre les fonctions :
Puis cette section clé qui est la déclaration de la fonction :
strlen(string $string): int
Dans laquelle on va retrouver le ou les paramètres et les valeurs de retour. On va préciser ces 2 points.
Les paramètres d’une fonction sont des variables spécifiées lors de la définition de la fonction, qui vont transmettre des valeurs ou des données à la fonction au moment où elle est appelée. Ils servent donc à personnaliser le comportement de la fonction selon des valeurs fournies, ce qui la rend réutilisable pour différentes situations.
Pour strlen, le paramètre est la chaine de caractères pour laquelle on souhaite connaitre la longueur. Et strlen va fonctionner pour n’importe quelle chaine de caractères.
Les valeurs de retour d’une fonction sont la ou les données qu’une fonction renvoie à la fin de son exécution, pour que d’autres parties du code puisse utiliser ce résultat.
Pour strlen, il y a une seule valeur de retour qui est donc la longueur de la chaine.
Les paramètres et les valeurs de retour sont typées. C’est à dire qu’on spécifie à l’aide d’un mot clé du langage ce que vont contenir les éléments de notre fonction. Lors de l’exécution du code, si ce typage n’est pas respecté, une erreur sera renvoyée et l’exécution du code interrompue.
Voici les types des différentes variables que l’on a vu ensemble jusqu’ici et qu’il est important de connaitre dès maintenant :
Pour en savoir plus sur le typage et ses subtilités, tu peux te référer à cet article (un peu plus avancé techniquement) : Bonnes pratiques PHP : typage et comparaison stricte.
Si on relit avec tous ces éléments la description de la fonction, ça donnerait :
« La fonction strlen permet de calculer la longueur d’une chaine de caractères. Cette fonction prend en paramètre une chaine de caractères, et retourne la longueur de cette chaine, sous la forme d’un entier. »
Et voici un exemple d’utilisation :
$mot = 'Bonjour';
$phrase = 'Comment ça va ?';
$longueurMot = strlen($mot);
$longueurPhrase = strlen($phrase);
echo 'Le mot contient ' . $longueurMot . ' caractères.';
echo 'La phrase contient ' . $longueurPhrase . ' caractères.';
La fonction strlen est un outil que je peux utiliser quand je veux dans mon code.
En plus des 1000+ fonctions déjà disponibles, il est également possible de créer ses propres fonctions.
Cela permet de créer ses propres outils, réutilisables, liés aux problématiques de son programme, son application, son site. On peut ranger à un seul endroit du code qui serait exécuté plusieurs fois à différents endroits de son programme. On peut ranger son code plus proprement en mettant à un seul endroit une portion de code plus longue ou plus complexe.
Je propose ici un plan de création de ses propres fonctions (que l’on va mettre en œuvre juste après) :
Pour l’exemple, on va créer une fonction qui permet de créer une phrase de présentation à partir du prénom et de l’âge d’une personne.
Etape 1 : le mot clé function
function
Etape 2 : le nommage. On va appeler cette fonction « phraseDePresentation »
function phraseDePresentation()
{ // Contrairement aux boucles et aux conditions, on passe à la ligne
}
Etape 3 : les paramètres. Une chaîne de caractères pour le prenom, un entier pour l’age
function phraseDePresentation(string $prenom, int $age)
{
}
Etape 4 : Le retour. C’est ce que la fonction va renvoyer au programme qui l’utilise. Ici on retourne donc une phrase.
function phraseDePresentation(string $prenom, int $age): string
{
return $phrase; // En l'état ce code renvoie une erreur car $phrase n'a pas été définie
}
Etape 5 : la logique complète de la fonction, on va faire de la concaténation
function phraseDePresentation(string $prenom, int $age): string
{
$phrase = '';
$phrase .= $prenom;
$phrase .= ' a ';
$phrase .= $age';
$phrase .= ' ans.';
return $phrase;
}
Au début, on a tendance à coder la fonction de haut en bas, à définir le type de retour en cours de route, etc. Je t’invite vraiment à suivre ces étapes, pour surtout bien concevoir la déclaration de ta fonction avant de la coder. Avec la déclaration, il s’agit de faire un « plan » avant de coder la fonction.
Cette notion de scope (ou portée) n’a pas encore été abordée car le scope est partagé tant qu’on reste avec les notions de variables, tableaux, conditions et boucles. Mais ça change avec les fonctions.
Cela veut dire que certaines variables qui sont dans un même fichier de code, ne sont pour autant pas accessibles à tous les endroits du code. Si on ne comprend pas ça correctement, on peut s’emmêler les pinceaux entre la création et l’utilisation d’une fonction et/ou générer des erreurs lors de l’écriture de son code.
Voici un exemple pour illustrer tout ça en reprenant la fonction créée juste avant :
// Considérons que je suis dans le fichier index.php
// Je crée ma fonction :
function phraseDePresentation(string $prenom, int $age): string
{
$phrase = '';
$phrase .= $prenom;
$phrase .= ' a ';
$phrase .= $age';
$phrase .= ' ans.';
return $phrase;
}
// Ici, si je fais echo $prenom, echo $age ou echo $phrase, j'aurais toujours une erreur, ces variables n'existent pas dans le scope principal, elles n'existent que dans le scope de la fonction phraseDePresentation()
// Si maintenant je crée ces variables :
$prenomDeMonAmi = 'Lucien';
$ageDeMonAmi = 27;
echo phraseDePresentation($prenomDeMonAmi, $ageDeMonAmi);
// Ce code fonctionne parfaitement
// Il y a une différence entre les paramètres dans la déclaration de la fonction et les variables utilisées par la fonction lors de son appel
// $prenom, $age, $phrase n'existent toujours pas ici
Pour bien comprendre ce principe, il faut considérer que tout se qui se passe dans une fonction… reste dans une fonction. Il n’y a aucun lien entre les variables du programme principal et les variables utilisées dans le corps d’une fonction pour la logique même de la fonction.
C’est pour ça d’ailleurs qu’on va avoir vite tendance à ranger les fonctions dans des fichiers dédiés et à ne surtout pas les intégrer au milieu d’un programme.
Techniquement, une fonction peut avoir autant de paramètres qu’on le souhaite. Avant il était intéressant tout de même de limiter ce nombre de paramètres à 3 ou 4 maximum. Depuis PHP 8 et les paramètres nommés, on a moins cette contrainte. On va d’abord regarder comment on faisait « avant » pour gérer des fonctions avec beaucoup de paramètres, et comment on peut faire « maintenant ».
Bien que cette méthode puisse désormais être considérée comme obsolète, il n’est pas impossible de retomber dessus dans un repo Github ou dans une codebase « âgée » dans laquelle il était courant d’utiliser cette technique. C’est donc bien de la connaitre, à minima pour la comprendre si on tombe dessus.
Imaginons que j’ai besoin de créer une fonction pour construire une balise HTML <input … />. Les possibilités de personnalisation sont nombreuses : type, value, placeholder, etc.
Je peux donc créer une fonction qui aura autant de paramètres que de possibilités de personnalisation :
function input(string $name, string $type = 'text', string $value = '', string $placeholder = '', string $id = '', bool $required = false): string
{
// Détails de ma fonction
}
// Je peux l'appeler de cette façon :
echo input('prenom');
echo input('age', 'number');
// Mais si je ne veux paramétrer que le placeholder, je me retrouve avec :
echo input('prenom', 'text', '', 'Entrez votre prénom');
// Ou si je veux que l'âge soit obligatoire :
echo input('age', 'number', '', '', '', true);
On voit dans les 2 derniers exemples que la lisibilité de l’appel de la fonction n’est pas optimale. Si je devine à quoi correspondent les 2 premiers paramètres, les 3 suivants sont tous à ‘ ‘ et donc difficiles à comprendre. Même le true à la fin n’est pas intuitif.
L’idée est donc de limiter le nombre de paramètres à seulement ceux qui sont obligatoires et d’avoir un paramètre $options :
function input(string $name, array $options = []): string
{
// Traitement de la value
if (isset($options['value'])) {
// Prise en considération de cette option
}
// Valeur par défaut pour le type
$type = $options['type'] ?? 'text';
// ...
}
// Lors de l'appel de ma fonction, en reprenant les exemples précédents, j'aurais donc :
echo input('prenom');
echo input('age', ['type' => 'number']);
echo input('prenom', ['placeholder' => 'Entre votre prénom']);
echo input('age', ['type' => 'number', 'required' => true]);
Les appels des fonctions sont donc ici beaucoup plus lisibles et compréhensibles. Il n’y a aucune interprétation possible sur les options qui sont gérées et pas besoin de retenir dans quel ordre les paramètres ont été indiqués dans la déclaration de la fonction.
On garde la première déclaration de fonction, avec tous les paramètres :
function input(
string $name,
string $type = 'text',
string $value = '',
string $placeholder = '',
string $id = '',
bool $required = false
): string
{
// Détails de ma fonction
}
Mais les appels sont cette fois différents :
echo input(name: 'prenom', placeholder: 'Entre votre prénom');
echo input(name: 'age', type: 'number', required: true]);
Ce sont désormais les noms qui vont s’occuper des correspondances. On peut donc créer autant de paramètres que l’on veut puisqu’on a plus à se soucier de leur ordonnancement lorsqu’on les appelle, grâce aux valeurs par défaut définies.
Pour aller + loin : PHP 8 : named arguments (en anglais)
La récursivité est une technique où une fonction s’appelle elle même. Elle est particulièrement utile pour les tâches qui peuvent être définies de manière répétitives. On peut l’utiliser également dans le même genre de situation qu’un while, c’est à dire quand on ne sait pas d’avance combien d’itérations ou d’exécutions de la fonction il va falloir réaliser pour atteindre le résultat.
Un exemple mathématique avec la fonction factorielle :
// En mathématique, "factorielle de 5" vaut 5 x 4 x 3 x 2 x 1, soit 120.
// Voici comment coder ce calcul :
function factorielle (int $n): int
{
if ($n <= 1) {
return 1;
}
return $n * factorielle($n - 1);
}
// Et donc factorielle(5); vaut 120
Un peu d’explications :
Ce n’est pas très simple à comprendre au début mais avec un peu d’exercice, ça devient plus clair !
Voici quelques cas où la récursivité est intéressante à utiliser (mais pas automatique ou obligatoire) :
Pour t’entrainer, n’hésite pas à découvrir nos (quelques) exercices de programmation autour de la récursivité.
Les fonctions sont une base fondamentale de la programmation et de l’algorithmie en général. Cela permet d’organiser son code de manière structurée et de créer sa propre boite à outils liée à son projet, son contexte, etc.
Maintenant que tu maitrises les fonctions, tu peux t’entrainer sur tous les challenges de code du niveau intermédiaire en essayant à chaque fois de créer une ou plusieurs fonctions. Pense aussi à parcourir la documentation officielle de temps pour être sûr de ne pas réinventer la roue en codant une fonction qui existerait déjà, ou en créant un algorithme complexe alors qu’il suffirait d’utiliser une ou deux fonctions natives pour résoudre le problème !
Pour aller + loin sur les fonctions PHP :
La prochaine étape, ce sera la programmation orientée objet ! En attendant, n’hésite pas à faire un tour sur nos autres articles techniques ou corrigés en lien avec PHP, tu as encore plein de choses à découvrir, apprendre et mettre en pratique 😉
Other content to discover