Fonctions et tableaux en PHP
Calculer une moyenne, vérifier un mot de passe, trier une liste d'élèves : on écrit ces traitements une seule fois, dans des fonctions, et on range les données dans des tableaux. Cette fiche montre comment PHP les fait vivre en mémoire, et les pièges qui surprennent même des développeurs expérimentés.
Après cette fiche, tu sais
- déclarer une fonction avec des paramètres typés, des valeurs par défaut et un type de retour ;
- prévoir ce qu'une fonction voit (la portée) et ce qu'elle modifie (valeur ou référence) ;
- créer, parcourir et modifier des tableaux indexés et associatifs sans perdre une clé ;
- employer les fonctions natives des tableaux, et
password_hash()pour les mots de passe.
Paramètres, types et return
Une fonction reçoit des paramètres, peut annoncer leur type et celui de sa valeur de retour, et renvoie un résultat avec return, qui termine aussitôt son exécution. Sans return, elle renvoie null.1
<?php
function moyenne(array $notes): float
{
return round(array_sum($notes) / count($notes), 2);
}
function mention(float $m, float $seuil = 4.0): string
{
return $m >= $seuil ? 'suffisant' : 'insuffisant';
}
echo moyenne([5, 4.5, 3.5]), "\n";
echo mention(moyenne([5, 4.5, 3.5])), "\n";
echo mention(3.9), "\n";
echo mention(seuil: 3.5, m: 3.9), "\n"; // arguments nommés
4.33 suffisant insuffisant suffisant
Le paramètre est la variable déclarée ($notes) ; l'argument est la valeur passée à l'appel ([5, 4.5, 3.5]).
$seuil = 4.0 rend le paramètre facultatif. Les paramètres facultatifs se placent après les obligatoires.1
Depuis PHP 8.0, on peut passer un argument par le nom de son paramètre, dans n'importe quel ordre : mention(seuil: 3.5, m: 3.9).1
array, float, string : vérifiés à l'appel ; une valeur impossible à accepter lève une TypeError.1
La pile d'appels
Fais défiler : pour exécuter echo mention(moyenne([5, 4.5, 3.5]));, PHP empile un cadre par fonction appelée, puis le retire quand elle renvoie sa valeur.
Le script démarre
Types souples ou stricts
Par défaut, PHP convertit une valeur vers le type attendu quand c'est possible : la chaîne '5' devient l'entier 5. Avec declare(strict_types=1); en tête de fichier, seule une valeur du bon type est acceptée (un int reste admis là où un float est attendu).1
<?php
declare(strict_types=1);
function double(int $n): int
{
return $n * 2;
}
echo double(5), "\n";
echo double('5'); // sans strict_types : 10
10 Fatal error: Uncaught TypeError: double(): Argument #1 ($n) must be of type int, string given
Une fonction qui affiche son résultat avec echo ne le renvoie pas : elle renvoie null. Impossible alors de réutiliser le résultat dans un calcul ou un test. Une fonction calcule et renvoie ; c'est l'appelant qui décide d'afficher.1
Reconstruis la fonction moyenne
Cinq lignes mélangées : la définition, puis un appel qui affiche le résultat.
Ce qu'une fonction voit, ce qu'elle modifie
Une variable utilisée dans une fonction est locale : les variables du script ne sont pas visibles à l'intérieur. C'est différent de JavaScript ou du C, où une fonction lit les variables extérieures.2
<?php
$taux = 0.081; // TVA suisse, taux normal
function ttc(float $prix): float
{
return round($prix * (1 + $taux), 2); // $taux n'existe pas ici
}
echo ttc(100);
Warning: Undefined variable $taux 100
PHP prévient, puis calcule avec null : 100 × (1 + 0) = 100, un prix faux sans erreur bloquante. Fais défiler : la correction, puis ce qui se passe quand une fonction reçoit un tableau.5
Le script a sa variable $taux, la fonction a son paramètre $prix. Dans ttc(), $taux n'existe pas : Warning, puis un résultat faux.2
La bonne correction : faire de $taux un paramètre. À l'appel, sa valeur est copiée dans la fonction. Le mot-clé global marcherait aussi, mais cache une dépendance.2
Un tableau passé à une fonction est lui aussi copié : la fonction ajoute un 6 à sa copie. Chez l'appelant, $a compte toujours 2 notes.1
Avec & devant le paramètre, la fonction travaille sur le tableau de l'appelant lui-même : après l'appel, $a compte 3 notes.1
Une fonction fléchée fn capture automatiquement les variables du script dont elle se sert, par valeur : $taux est visible, sans paramètre.1
<?php
$taux = 0.081;
function ttc(float $prix, float $taux): float
{
return round($prix * (1 + $taux), 2);
}
echo ttc(100, $taux), "\n";
$ttcFleche = fn(float $prix) => round($prix * (1 + $taux), 2);
echo $ttcFleche(100), "\n";
function bonus(array &$notes): void // & : par référence
{
$notes[] = 6;
}
$a = [5, 4];
bonus($a);
echo count($a);
108.1 108.1 3
La fonction reçoit une copie : modifier son paramètre ne change rien chez l'appelant.1
La fonction modifie la variable de l'appelant. À réserver aux cas où c'est le but, et à annoncer dans le nom.1
Une variable static reste locale, mais garde sa valeur d'un appel à l'autre : utile pour un compteur.2
fn($x) => expression : une petite fonction sans nom, qui capture par valeur les variables extérieures qu'elle utilise.1
Que va afficher ce code ?
Quatre fonctions courtes, toutes exécutées avec PHP 8.4.
Des valeurs rangées sous des clés
Un tableau PHP est une table ordonnée qui associe des valeurs à des clés, entières ou textuelles.3 Écrit sans clés, ['pomme', 'poire'] numérote à partir de 0. Avec $t[] = …, PHP choisit la clé : la plus grande clé entière déjà utilisée, plus 1. Et unset() retire un élément sans renuméroter les autres.3
<?php $fruits = ['pomme', 'poire', 'kiwi']; $fruits[] = 'figue'; // clé 3 unset($fruits[1]); // retire 'poire' : clés 0, 2, 3 $fruits[] = 'mangue'; // clé 4, pas 1 print_r($fruits); echo count($fruits), "\n"; $fruits = array_values($fruits); // clés 0 à 3 print_r($fruits);
Array
(
[0] => pomme
[2] => kiwi
[3] => figue
[4] => mangue
)
4
Array
(
[0] => pomme
[1] => kiwi
[2] => figue
[3] => mangue
)Le trou que unset() laisse
Fais défiler : les instructions ci-dessus, une par une, avec les clés au-dessus des cases.
Trois fruits
Après unset($fruits[1]), une boucle for ($i = 0; $i < count($fruits); $i++) lit la clé 1, qui n'existe plus (Warning: Undefined array key 1), et n'atteint jamais la dernière case. Pour parcourir un tableau, foreach suit les clés réelles.3
Quelle clé ?
Quatre petits tableaux, testés avec PHP 8.4.
Des clés qui ont un nom
Avec 'cle' => valeur, on choisit soi-même les clés : un tableau associatif décrit une chose par ses propriétés, et peut en contenir d'autres.3
<?php
$eleve = [
'prenom' => 'Zoé',
'classe' => '2M3',
'notes' => [6, 5.5],
];
echo $eleve['prenom'], "\n";
$eleve['email'] = 'zoe@example.com'; // nouvelle clé
foreach ($eleve as $cle => $valeur) {
if (is_array($valeur)) {
$valeur = implode(', ', $valeur);
}
echo "$cle : $valeur\n";
}
Zoé prenom : Zoé classe : 2M3 notes : 6, 5.5 email : zoe@example.com
Pour savoir si une clé existe, deux outils, qui diffèrent quand la valeur vaut null :3
<?php
$eleve = ['prenom' => 'Zoé', 'remarque' => null];
var_dump(isset($eleve['remarque'])); // la valeur est null
var_dump(array_key_exists('remarque', $eleve)); // la clé existe
echo $eleve['email'] ?? "pas d'adresse"; // clé absente
bool(false) bool(true) pas d'adresse
Vrai si la clé existe et que sa valeur n'est pas null.3
Vrai dès que la clé existe, même avec la valeur null.3
La valeur si elle existe et n'est pas null, sinon la valeur par défaut, sans avertissement.
Une liste d'élèves est un tableau de tableaux associatifs : $eleves[0]['prenom'].
echo $eleve['email']; sans vérification affiche Warning: Undefined array key "email". Une saisie de formulaire peut toujours manquer : on lit avec ??.
Trier, filtrer, transformer
PHP fournit des dizaines de fonctions pour les tableaux. Pour chacune, deux questions : modifie-t-elle le tableau ou en renvoie-t-elle un nouveau ? Garde-t-elle les clés ?
| Fonction | Ce qu'elle fait | Clés |
|---|---|---|
sort($t) | trie sur place, renvoie true | renumérotées |
usort($t, $f) | trie sur place selon une fonction de comparaison | renumérotées |
array_filter($t, $f) | renvoie les éléments pour lesquels $f répond vrai | gardées, avec des trous |
array_map($f, $t) | renvoie $f appliquée à chaque élément | gardées (un seul tableau) |
array_values($t) | renvoie les valeurs | renumérotées dès 0 |
in_array($v, $t) | la valeur est-elle présente ? (avec ==) | sans objet |
Sources des comportements : la documentation de chaque fonction.3 Exemple avec des prix en CHF et la TVA suisse de 8,1 % :5
<?php $prix = ['cahier' => 12.5, 'stylo' => 3.2, 'sac' => 48.0]; $ttc = array_map(fn($p) => round($p * 1.081, 2), $prix); print_r($ttc); $notes = [5, 3.5, 6, 4, 2.5]; $suffisantes = array_filter($notes, fn($n) => $n >= 4); print_r($suffisantes);
Array
(
[cahier] => 13.51
[stylo] => 3.46
[sac] => 51.89
)
Array
(
[0] => 5
[2] => 6
[3] => 4
)Une chaîne de traitements
Fais défiler : les notes passent par array_filter, array_values, sort, puis implode. Surveille les clés.
Cinq notes
sort() trie le tableau qu'on lui donne et renvoie true. Écrire $t = sort($t); remplace le tableau trié par… true.3
in_array('1e1', ['10']) répond true, car les deux chaînes numériques valent 10. Un troisième argument true impose === : in_array('1e1', ['10'], true) répond false.3
Modifie le tableau, ou en renvoie un nouveau ?
Dix opérations courantes. Range chacune selon ce qu'elle fait au tableau $t.
Une fonction native qui protège : password_hash()
Un mot de passe ne se stocke jamais en clair, ni chiffré : on garde son empreinte, calculée par une fonction à sens unique. L'empreinte inclut un sel aléatoire, pour que deux mots de passe identiques donnent deux empreintes différentes, et elle doit être lente à calculer, pour freiner les essais en masse.4 En PHP, password_hash() fait tout cela ; password_verify() vérifie une saisie.4
<?php
$hash = password_hash('Chat-Violet-42!', PASSWORD_DEFAULT);
echo strlen($hash), "\n"; // 60 caractères (bcrypt)
echo substr($hash, 0, 7), "\n"; // algorithme et coût
var_dump(password_verify('Chat-Violet-42!', $hash));
var_dump(password_verify('chat-violet-42!', $hash)); // une majuscule de moins
var_dump($hash === password_hash('Chat-Violet-42!', PASSWORD_DEFAULT));
60 $2y$12$ bool(true) bool(false) bool(false)
L'empreinte éclatée
Fais défiler : une vraie empreinte bcrypt, produite par PHP 8.4, se sépare en quatre morceaux, puis sert à vérifier deux saisies.
60 caractères
Aujourd'hui bcrypt ; la constante peut changer dans une future version. On stocke l'empreinte dans une colonne de 255 caractères.4
Le nombre qui suit $2y$ est le logarithme en base 2 du nombre de tours : 12 donne 212 = 4096 tours. Le coût par défaut est passé de 10 à 12 avec PHP 8.4.4
Tiré au hasard à chaque appel ; ne jamais fournir le sien. Il est rangé dans l'empreinte, avec l'algorithme et le coût.4
bcrypt ne tient compte que des 72 premiers octets du mot de passe.4
Ces fonctions sont rapides et sans sel : un attaquant qui vole la base peut tester des milliards de mots de passe, et deux comptes au même mot de passe ont la même empreinte. L'OWASP les écarte pour les mots de passe.4
password_hash($mdp, PASSWORD_ARGON2ID) l'utilise ; password_verify() lit l'algorithme dans l'empreinte et marche avec les deux.4Sept bonnes pratiques
- une fonction, une tâche, un nom en verbe (
calculerMoyenne,verifierNote) ; - typer les paramètres et le retour, et envisager
declare(strict_types=1);; - renvoyer avec
returnplutôt qu'afficher avececho; - passer en paramètre ce dont la fonction a besoin, plutôt que
global; - parcourir les tableaux avec
foreach, et renuméroter avecarray_values()si les clés comptent ; - lire une clé qui peut manquer avec
??, et chercher avecin_array(…, true); - pour les mots de passe :
password_hash()etpassword_verify(), rien d'autre.
Trois exercices corrigés
Tous les corrigés ont été exécutés avec PHP 8.4.
1Écris une fonction compterInsuffisantes(array $notes): int qui compte les notes inférieures à 4.Voir le corrigé
<?php
function compterInsuffisantes(array $notes): int
{
$n = 0;
foreach ($notes as $note) {
if ($note < 4) {
$n++;
}
}
return $n;
}
echo compterInsuffisantes([5, 3.5, 6, 3, 4]), "\n";
echo count(array_filter([5, 3.5, 6, 3, 4], fn($x) => $x < 4));
2 2
La seconde ligne obtient le même résultat avec array_filter puis count. Le 4 n'est pas compté : il est suffisant.
2Trie une liste d'élèves de la meilleure à la moins bonne moyenne, et affiche le classement.Voir le corrigé
<?php
$eleves = [
['prenom' => 'Léa', 'moyenne' => 5.25],
['prenom' => 'Noah', 'moyenne' => 3.75],
['prenom' => 'Zoé', 'moyenne' => 5.75],
];
usort($eleves, fn($a, $b) => $b['moyenne'] <=> $a['moyenne']);
foreach ($eleves as $rang => $e) {
echo ($rang + 1) . '. ' . $e['prenom'] . ' (' . $e['moyenne'] . ")\n";
}
1. Zoé (5.75) 2. Léa (5.25) 3. Noah (3.75)
usort trie avec une fonction qui compare deux éléments ; <=> renvoie le nombre négatif, nul ou positif attendu. En écrivant $b avant $a, on trie dans l'ordre décroissant.3
3Ce code devrait afficher « Total : 32.43 ». Il affiche autre chose : trouve les deux erreurs.Voir le corrigé
<?php
$taux = 0.081;
function prixTTC($prix)
{
echo round($prix * (1 + $taux), 2);
}
$total = prixTTC(10) + prixTTC(20);
echo "\nTotal : $total";
Warning: Undefined variable $taux 10 Warning: Undefined variable $taux 20 Total : 0
1) $taux n'est pas visible dans la fonction. 2) La fonction affiche au lieu de renvoyer : elle renvoie null, et null + null donne 0. Version corrigée :
<?php
function prixTTC(float $prix, float $taux = 0.081): float
{
return round($prix * (1 + $taux), 2);
}
$total = prixTTC(10) + prixTTC(20);
echo "Total : $total";
Total : 32.43
La fiche en huit lignes
Teste-toi
Sources
- The PHP Group, PHP Manual : « Function arguments » (par valeur, par référence, valeurs par défaut, arguments nommés), « Returning values », « Arrow Functions », « Type declarations » (strict_types). arguments, return, fonctions fléchées, types (php.net)
- The PHP Group, PHP Manual : « Variable scope » (portée locale, global, static). php.net
- The PHP Group, PHP Manual : « Arrays » (clés, ajout, unset), et les fonctions array_filter, array_map, sort, usort, in_array, array_key_exists. tableaux, array_filter, array_map, sort, usort, in_array, array_key_exists (php.net)
- The PHP Group, PHP Manual : « password_hash », « Password hashing constants », « crypt » (format CRYPT_BLOWFISH) ; OWASP, Password Storage Cheat Sheet. password_hash, constantes, crypt (php.net), OWASP
- Administration fédérale des contributions (AFC), Taux de TVA en Suisse : taux normal de 8,1 % depuis le 1er janvier 2024. estv.admin.ch
Fiche écrite et sourcée en octobre 2026. Tout le code a été exécuté avec PHP 8.4.