Informatique · PHP

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.

tableau 5 4.5 3.5 012 clés fonction moyenne() array → float 4.33 return round(13 / 3, 2)
Une variable créée en dehors d'une fonction : la fonction peut-elle la lire directement ? En JavaScript, oui. En PHP… réponse dans la notion 2.

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.
1Notion 1 · Fonctions

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

Deux fonctions qui collaborentPHP
<?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
Paramètre et argument

Le paramètre est la variable déclarée ($notes) ; l'argument est la valeur passée à l'appel ([5, 4.5, 3.5]).

Valeur par défaut

$seuil = 4.0 rend le paramètre facultatif. Les paramètres facultatifs se placent après les obligatoires.1

Arguments nommés

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

Types

array, float, string : vérifiés à l'appel ; une valeur impossible à accepter lève une TypeError.1

Scène 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.

Scène 1 · Pile d'appels

Le script démarre

pile d'appels le sommet s'exécute

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

Le même appel, deux modesPHP
<?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
Piège : echo au lieu de return

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

Exercice · remettre dans l'ordre

Reconstruis la fonction moyenne

Cinq lignes mélangées : la définition, puis un appel qui affiche le résultat.

2Notion 2 · Portée

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

Une variable du script, invisiblePHP
<?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

script (portée globale)
Étape 1 sur 5 · deux mondes

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

Étape 2 sur 5 · le passer en argument

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

Étape 3 sur 5 · un tableau copié

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

Étape 4 sur 5 · par référence

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

Étape 5 sur 5 · fonction fléchée

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

Réponse à ma question : non. En PHP, une fonction ne voit que ses paramètres et ses variables locales. Si elle a besoin d'une valeur, on la lui passe en argument.
Les correctionsPHP
<?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
Par valeur (défaut)

La fonction reçoit une copie : modifier son paramètre ne change rien chez l'appelant.1

Par référence (&)

La fonction modifie la variable de l'appelant. À réserver aux cas où c'est le but, et à annoncer dans le nom.1

static

Une variable static reste locale, mais garde sa valeur d'un appel à l'autre : utile pour un compteur.2

fn (fonction fléchée)

fn($x) => expression : une petite fonction sans nom, qui capture par valeur les variables extérieures qu'elle utilise.1

Exercice · à toi

Que va afficher ce code ?

Quatre fonctions courtes, toutes exécutées avec PHP 8.4.

3Notion 3 · Tableaux

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

Ajouter, retirer, renuméroterPHP
<?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
)
Scène 2

Le trou que unset() laisse

Fais défiler : les instructions ci-dessus, une par une, avec les clés au-dessus des cases.

Scène 2 · Tableau en mémoire

Trois fruits

$fruits

Piège : for et count sur un tableau troué

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

Exercice · prévoir

Quelle clé ?

Quatre petits tableaux, testés avec PHP 8.4.

4Notion 4 · Tableaux associatifs

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

Une élève et ses notesPHP
<?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

isset ou array_key_existsPHP
<?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
isset($t['k'])

Vrai si la clé existe et que sa valeur n'est pas null.3

array_key_exists('k', $t)

Vrai dès que la clé existe, même avec la valeur null.3

$t['k'] ?? défaut

La valeur si elle existe et n'est pas null, sinon la valeur par défaut, sans avertissement.

Tableaux imbriqués

Une liste d'élèves est un tableau de tableaux associatifs : $eleves[0]['prenom'].

Piège : lire une clé absente

echo $eleve['email']; sans vérification affiche Warning: Undefined array key "email". Une saisie de formulaire peut toujours manquer : on lit avec ??.

5Notion 5 · Fonctions natives

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 ?

FonctionCe qu'elle faitClés
sort($t)trie sur place, renvoie truerenumérotées
usort($t, $f)trie sur place selon une fonction de comparaisonrenumérotées
array_filter($t, $f)renvoie les éléments pour lesquels $f répond vraigardées, avec des trous
array_map($f, $t)renvoie $f appliquée à chaque élémentgardées (un seul tableau)
array_values($t)renvoie les valeursrenumé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

array_map et array_filterPHP
<?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
)
Scène 3

Une chaîne de traitements

Fais défiler : les notes passent par array_filter, array_values, sort, puis implode. Surveille les clés.

Scène 3 · Fonctions natives

Cinq notes

Piège : $t = sort($t);

sort() trie le tableau qu'on lui donne et renvoie true. Écrire $t = sort($t); remplace le tableau trié par… true.3

Piège : in_array compare avec ==

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

Exercice · classer

Modifie le tableau, ou en renvoie un nouveau ?

Dix opérations courantes. Range chacune selon ce qu'elle fait au tableau $t.

6Notion 6 · Mots de passe

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

Créer et vérifier une empreintePHP
<?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)
Scène 4

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.

Scène 4 · Empreinte bcrypt

60 caractères

password_verify(

PASSWORD_DEFAULT

Aujourd'hui bcrypt ; la constante peut changer dans une future version. On stocke l'empreinte dans une colonne de 255 caractères.4

Coût

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

Sel

Tiré au hasard à chaque appel ; ne jamais fournir le sien. Il est rangé dans l'empreinte, avec l'algorithme et le coût.4

72 octets

bcrypt ne tient compte que des 72 premiers octets du mot de passe.4

Piège : md5() et sha1()

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

Et Argon2id ?L'OWASP place Argon2id en tête de ses recommandations et garde bcrypt pour les systèmes existants. Quand PHP est compilé avec Argon2, password_hash($mdp, PASSWORD_ARGON2ID) l'utilise ; password_verify() lit l'algorithme dans l'empreinte et marche avec les deux.4
Retiens les deux gestes : password_hash() à l'inscription, password_verify() à la connexion. Jamais de comparaison d'empreintes à la main.
Habitudes de pro

Sept 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 return plutôt qu'afficher avec echo ;
  • passer en paramètre ce dont la fonction a besoin, plutôt que global ;
  • parcourir les tableaux avec foreach, et renuméroter avec array_values() si les clés comptent ;
  • lire une clé qui peut manquer avec ??, et chercher avec in_array(…, true) ;
  • pour les mots de passe : password_hash() et password_verify(), rien d'autre.
Entraînement

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
À retenir

La fiche en huit lignes

Fonctionfunction nom(type $p = défaut): type { return …; } ; sans return, elle renvoie null.
Typesconvertis par défaut ; declare(strict_types=1) exige le bon type, sinon TypeError.
Portéeune fonction ne voit pas les variables du script : on les passe en argument ; fn les capture par valeur.
Argumentscopiés par défaut ; & devant le paramètre pour modifier la variable de l'appelant.
Clés$t[] = x prend la plus grande clé entière + 1 ; unset() ne renumérote pas ; array_values() si.
Associatifs'cle' => valeur ; isset est faux pour une valeur null, array_key_exists non.
Nativessort trie sur place et renvoie true ; array_filter garde les clés ; in_array(…, true) pour ===.
Mots de passepassword_hash() à l'inscription, password_verify() à la connexion ; colonne de 255 caractères.
Dernière étape : le quiz. Douze questions tirées au hasard, différentes à chaque partie. Si tu te trompes, lis bien l'explication.
Quiz final

Teste-toi

Sources

  1. 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)
  2. The PHP Group, PHP Manual : « Variable scope » (portée locale, global, static). php.net
  3. 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)
  4. 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
  5. 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.

Glisser pour continuer vers La POO en PHP
Collège 2