Programmation PHP

Functions PHP

Maîtrisez les fonctions PHP de A à Z : création, fonctions natives, récursivité, closures et concepts avancés pour structurer votre code efficacement.

🔧 Création
📚 Natives
🔄 Récursives
⚡ Avancées

Bases des Fonctions PHP

Comprendre ce qu'est une fonction, pourquoi les utiliser et comment elles fonctionnent.

🎯 Qu'est-ce qu'une Fonction ?

Concept et Avantages :

🔧 Définition :

Une fonction est un bloc de code réutilisable qui effectue une tâche spécifique. Elle peut recevoir des paramètres en entrée et retourner une valeur.

✅ Avantages :
  • • Réutilisabilité du code
  • • Organisation et structure
  • • Facilité de maintenance
  • • Tests plus simples
  • • Lisibilité améliorée

Anatomie d'une Fonction :

// Structure d'une fonction PHP
function nomDeLaFonction($param1, $param2) {
// Corps de la fonction
$resultat = $param1 + $param2;
return $resultat; // Valeur retournée
}
// Appel de la fonction
$somme = nomDeLaFonction(5, 3);

📝 Syntaxe et Premiers Exemples

<?php
// 1. FONCTION SIMPLE SANS PARAMÈTRES
function direBonjour() {
    echo "Bonjour tout le monde !";
}

// Appel de la fonction
direBonjour(); // Affiche: Bonjour tout le monde !

// 2. FONCTION AVEC PARAMÈTRES
function saluer($nom) {
    echo "Bonjour " . $nom . " !";
}

saluer("Marie"); // Affiche: Bonjour Marie !

// 3. FONCTION AVEC VALEUR DE RETOUR
function additionner($a, $b) {
    return $a + $b;
}

$resultat = additionner(5, 3);
echo $resultat; // Affiche: 8

// 4. FONCTION AVEC PLUSIEURS PARAMÈTRES
function calculerAire($longueur, $largeur) {
    $aire = $longueur * $largeur;
    return $aire;
}

$surface = calculerAire(10, 5);
echo "Surface: " . $surface . " m²"; // Affiche: Surface: 50 m²

// 5. FONCTION AVEC PARAMÈTRES PAR DÉFAUT
function saluerAvecTitre($nom, $titre = "Monsieur") {
    return $titre . " " . $nom;
}

echo saluerAvecTitre("Dupont"); // Affiche: Monsieur Dupont
echo saluerAvecTitre("Martin", "Madame"); // Affiche: Madame Martin

// 6. FONCTION AVEC TYPE DE RETOUR SPÉCIFIÉ (PHP 7+)
function diviser(float $a, float $b): float {
    if ($b == 0) {
        throw new InvalidArgumentException("Division par zéro impossible");
    }
    return $a / $b;
}

echo diviser(10, 2); // Affiche: 5

// 7. FONCTION SANS VALEUR DE RETOUR (void)
function afficherMessage(string $message): void {
    echo "<p>" . htmlspecialchars($message) . "</p>";
}

afficherMessage("Ceci est un message sécurisé");
?>

Création de Fonctions Personnalisées

Apprenez à créer vos propres fonctions avec paramètres, types, et gestion d'erreurs.

⚙️ Paramètres et Arguments Avancés

<?php
// 1. FONCTION AVEC NOMBRE VARIABLE D'ARGUMENTS
function somme(...$nombres) {
    $total = 0;
    foreach ($nombres as $nombre) {
        $total += $nombre;
    }
    return $total;
}

echo somme(1, 2, 3); // Affiche: 6
echo somme(1, 2, 3, 4, 5); // Affiche: 15

// 2. FONCTION AVEC TYPES STRICTS
declare(strict_types=1);

function multiplier(int $a, int $b): int {
    return $a * $b;
}

echo multiplier(5, 3); // Affiche: 15
// multiplier(5.5, 3); // ERREUR avec strict_types

// 3. FONCTION AVEC PARAMÈTRES NOMMÉS (PHP 8+)
function creerUtilisateur(
    string $nom, 
    string $email, 
    int $age = 18, 
    bool $actif = true
) {
    return [
        'nom' => $nom,
        'email' => $email,
        'age' => $age,
        'actif' => $actif
    ];
}

// Appel avec paramètres nommés
$user = creerUtilisateur(
    nom: "Dupont", 
    email: "dupont@example.com", 
    actif: false
);

// 4. FONCTION AVEC RÉFÉRENCE (PASSAGE PAR RÉFÉRENCE)
function incrementer(&$valeur) {
    $valeur++;
}

$nombre = 5;
incrementer($nombre);
echo $nombre; // Affiche: 6 (modifié par référence)

// 5. FONCTION AVEC VALEURS PAR DÉFAUT COMPLEXES
function genererRapport(
    array $donnees, 
    string $format = 'html',
    array $options = ['titre' => 'Rapport', 'date' => null]
) {
    if ($options['date'] === null) {
        $options['date'] = date('Y-m-d');
    }
    
    return "Rapport {$options['titre']} du {$options['date']} en format $format";
}

echo genererRapport(['data1', 'data2']);

// 6. FONCTION AVEC UNION TYPES (PHP 8+)
function traiterDonnee(int|string|array $donnee): string {
    if (is_int($donnee)) {
        return "Nombre: " . $donnee;
    } elseif (is_string($donnee)) {
        return "Texte: " . $donnee;
    } elseif (is_array($donnee)) {
        return "Tableau: " . implode(', ', $donnee);
    }
}

echo traiterDonnee(42); // Nombre: 42
echo traiterDonnee("Hello"); // Texte: Hello
echo traiterDonnee([1, 2, 3]); // Tableau: 1, 2, 3

// 7. FONCTION AVEC NULLABLE TYPES
function obtenirUtilisateur(int $id): ?array {
    // Simule une recherche en base de données
    if ($id === 1) {
        return ['id' => 1, 'nom' => 'Admin'];
    }
    return null; // Utilisateur non trouvé
}

$user = obtenirUtilisateur(1);
if ($user !== null) {
    echo "Utilisateur trouvé: " . $user['nom'];
} else {
    echo "Utilisateur non trouvé";
}

// 8. FONCTION AVEC VALIDATION DES PARAMÈTRES
function calculerPourcentage(float $valeur, float $total): float {
    if ($total <= 0) {
        throw new InvalidArgumentException("Le total doit être positif");
    }
    
    if ($valeur < 0) {
        throw new InvalidArgumentException("La valeur ne peut pas être négative");
    }
    
    return ($valeur / $total) * 100;
}

try {
    echo calculerPourcentage(25, 100); // Affiche: 25
} catch (InvalidArgumentException $e) {
    echo "Erreur: " . $e->getMessage();
}
?>

Fonctions Natives PHP Essentielles

Découvrez les fonctions intégrées les plus utiles pour le traitement de chaînes, tableaux et dates.

📝 Fonctions de Chaînes de Caractères

<?php
// FONCTIONS DE CHAÎNES LES PLUS UTILISÉES

$texte = " Bonjour le Monde! ";
$email = "utilisateur@exemple.com";
$phrase = "PHP est un langage formidable";

// 1. LONGUEUR ET MANIPULATION DE BASE
echo strlen($texte); // Longueur: 19
echo trim($texte); // Supprime espaces: "Bonjour le Monde!"
echo strtoupper($texte); // Majuscules: " BONJOUR LE MONDE! "
echo strtolower($texte); // Minuscules: " bonjour le monde! "
echo ucfirst(trim($texte)); // 1ère lettre maj: "Bonjour le monde!"
echo ucwords(trim($texte)); // Chaque mot maj: "Bonjour Le Monde!"

// 2. RECHERCHE ET REMPLACEMENT
echo strpos($phrase, "PHP"); // Position: 0
echo str_replace("PHP", "JavaScript", $phrase); // Remplacement
echo str_ireplace("php", "Python", $phrase); // Remplacement insensible à la casse

// 3. EXTRACTION ET DÉCOUPAGE
echo substr($phrase, 0, 3); // Extrait: "PHP"
echo substr($phrase, -10); // 10 derniers: "formidable"
$mots = explode(" ", $phrase); // Découpe en tableau
print_r($mots);

// 4. VALIDATION ET TESTS
if (str_contains($email, "@")) {
    echo "Email valide";
}

if (str_starts_with($phrase, "PHP")) {
    echo "Commence par PHP";
}

if (str_ends_with($phrase, "formidable")) {
    echo "Se termine par formidable";
}

// 5. FORMATAGE AVANCÉ
$nom = "Jean";
$age = 25;

// sprintf pour formater
$message = sprintf("Bonjour %s, vous avez %d ans", $nom, $age);
echo $message;

// number_format pour les nombres
$prix = 1234.56;
echo number_format($prix, 2, ',', ' '); // 1 234,56

// 6. FONCTIONS UTILES POUR LA SÉCURITÉ
$input = "<script>alert('XSS')</script>";
echo htmlspecialchars($input); // Échapper HTML
echo strip_tags($input); // Supprimer tags HTML

// 7. EXPRESSIONS RÉGULIÈRES SIMPLES
$telephone = "+33-1-23-45-67-89";
if (preg_match('/^\+33-\d-\d{2}-\d{2}-\d{2}-\d{2}$/', $telephone)) {
    echo "Numéro français valide";
}

// Extraire tous les nombres d'une chaîne
$texteAvecNombres = "J'ai 25 ans et 3 chats";
preg_match_all('/\d+/', $texteAvecNombres, $matches);
print_r($matches[0]); // [25, 3]

// 8. FONCTIONS PRATIQUES AVANCÉES
function nettoyer($texte) {
    $texte = trim($texte);
    $texte = htmlspecialchars($texte);
    $texte = stripslashes($texte);
    return $texte;
}

function genererSlug($titre) {
    $slug = strtolower($titre);
    $slug = preg_replace('/[^a-z0-9]+/', '-', $slug);
    $slug = trim($slug, '-');
    return $slug;
}

echo genererSlug("Mon Premier Article!"); // mon-premier-article

// 9. CHIFFREMENT SIMPLE
$motDePasse = "monMotDePasse123";
$hash = password_hash($motDePasse, PASSWORD_DEFAULT);
echo $hash;

// Vérification
if (password_verify($motDePasse, $hash)) {
    echo "Mot de passe correct";
}

// 10. FONCTIONS MULTI-BYTES (UTF-8)
$texteUtf8 = "Café, naïve, 北京";
echo mb_strlen($texteUtf8); // Longueur correcte en UTF-8
echo mb_substr($texteUtf8, 0, 4); // Extraction UTF-8
echo mb_strtoupper($texteUtf8); // Majuscules UTF-8
?>

📋 Fonctions de Tableaux

<?php
// FONCTIONS DE TABLEAUX ESSENTIELLES

$fruits = ['pomme', 'banane', 'orange', 'kiwi'];
$notes = [12, 15, 8, 20, 14];
$personne = ['nom' => 'Dupont', 'age' => 30, 'ville' => 'Paris'];

// 1. INFORMATIONS SUR LE TABLEAU
echo count($fruits); // Nombre d'éléments: 4
echo sizeof($notes); // Alias de count()
var_dump(is_array($fruits)); // Vérifie si c'est un tableau: true
var_dump(empty($fruits)); // Vérifie si vide: false

// 2. AJOUT ET SUPPRESSION D'ÉLÉMENTS
array_push($fruits, 'mangue'); // Ajoute à la fin
array_unshift($fruits, 'fraise'); // Ajoute au début
$dernierFruit = array_pop($fruits); // Retire et retourne le dernier
$premierFruit = array_shift($fruits); // Retire et retourne le premier

// 3. RECHERCHE ET VÉRIFICATION
if (in_array('pomme', $fruits)) {
    echo "Pomme trouvée";
}

$position = array_search('banane', $fruits);
if ($position !== false) {
    echo "Banane trouvée à la position: $position";
}

if (array_key_exists('nom', $personne)) {
    echo "Clé 'nom' existe";
}

// 4. TRANSFORMATION ET FILTRAGE
$notesPlusUn = array_map(function($note) {
    return $note + 1;
}, $notes);

$bonnesNotes = array_filter($notes, function($note) {
    return $note >= 15;
});

$total = array_reduce($notes, function($carry, $note) {
    return $carry + $note;
}, 0);

// 5. TRI ET ORDRE
$nombresDesordres = [3, 1, 4, 1, 5, 9, 2, 6];
sort($nombresDesordres); // Tri croissant (réindexe)
rsort($nombresDesordres); // Tri décroissant (réindexe)

$personnesTri = [
    ['nom' => 'Alice', 'age' => 25],
    ['nom' => 'Bob', 'age' => 30],
    ['nom' => 'Charlie', 'age' => 20]
];

// Tri par âge
usort($personnesTri, function($a, $b) {
    return $a['age'] <=> $b['age'];
});

// 6. FUSION ET COMBINAISON
$fruits1 = ['pomme', 'banane'];
$fruits2 = ['orange', 'kiwi'];
$tousFruits = array_merge($fruits1, $fruits2);

$cles = ['nom', 'age', 'ville'];
$valeurs = ['Martin', 28, 'Lyon'];
$utilisateur = array_combine($cles, $valeurs);

// 7. EXTRACTION ET DÉCOUPAGE
$prendsDeuxPremiers = array_slice($fruits, 0, 2);
$prendsDeuxDerniers = array_slice($fruits, -2);

$morceau = array_splice($fruits, 1, 2); // Retire et retourne 2 éléments à partir de l'index 1

// 8. FONCTIONS MATHÉMATIQUES
echo max($notes); // Plus grande valeur: 20
echo min($notes); // Plus petite valeur: 8
echo array_sum($notes); // Somme: 69
echo array_product([2, 3, 4]); // Produit: 24

// 9. FONCTIONS AVANCÉES PRATIQUES
function obtenirStatsTableau(array $nombres): array {
    return [
        'count' => count($nombres),
        'sum' => array_sum($nombres),
        'average' => array_sum($nombres) / count($nombres),
        'min' => min($nombres),
        'max' => max($nombres)
    ];
}

$stats = obtenirStatsTableau($notes);
print_r($stats);

// 10. MANIPULATION DE TABLEAUX MULTIDIMENSIONNELS
$etudiants = [
    ['nom' => 'Alice', 'notes' => [15, 17, 12]],
    ['nom' => 'Bob', 'notes' => [18, 16, 14]],
    ['nom' => 'Charlie', 'notes' => [13, 15, 16]]
];

// Extraire tous les noms
$noms = array_column($etudiants, 'nom');
print_r($noms);

// Calculer moyenne pour chaque étudiant
$etudiantsAvecMoyenne = array_map(function($etudiant) {
    $etudiant['moyenne'] = array_sum($etudiant['notes']) / count($etudiant['notes']);
    return $etudiant;
}, $etudiants);

// 11. FONCTIONS DE CLÉS ET VALEURS
$cles = array_keys($personne); // ['nom', 'age', 'ville']
$valeurs = array_values($personne); // ['Dupont', 30, 'Paris']
$inverse = array_flip(['a' => 1, 'b' => 2]); // [1 => 'a', 2 => 'b']

// 12. TABLEAUX UNIQUES ET DIFFÉRENCES
$nombres = [1, 2, 2, 3, 3, 4];
$nombresUniques = array_unique($nombres); // [1, 2, 3, 4]

$groupe1 = ['Alice', 'Bob', 'Charlie'];
$groupe2 = ['Bob', 'David', 'Eve'];
$seulement1 = array_diff($groupe1, $groupe2); // ['Alice', 'Charlie']
$communs = array_intersect($groupe1, $groupe2); // ['Bob']
?>

Fonctions Anonymes et Closures

Explorez les fonctions anonymes, closures et arrow functions pour une programmation moderne.

Fonctions Anonymes et Closures

// FONCTIONS ANONYMES ET CLOSURES

// 1. FONCTION ANONYME SIMPLE
$saluer = function($nom) {
    return "Bonjour " . $nom;
};

echo $saluer("Marie"); // Bonjour Marie

// 2. FONCTION ANONYME AVEC USE (CLOSURE)
$multiplicateur = 3;

$multiplier = function($nombre) use ($multiplicateur) {
    return $nombre * $multiplicateur;
};

echo $multiplier(5); // 15

// 3. CLOSURE AVEC RÉFÉRENCE
$compteur = 0;

$incrementer = function() use (&$compteur) {
    $compteur++;
    return $compteur;
};

echo $incrementer(); // 1
echo $incrementer(); // 2
echo $compteur; // 2 (modifié par référence)

// 4. ARROW FUNCTIONS (PHP 7.4+)
$nombres = [1, 2, 3, 4, 5];

// Fonction classique
$carres1 = array_map(function($n) {
    return $n * $n;
}, $nombres);

// Arrow function (plus concise)
$carres2 = array_map(fn($n) => $n * $n, $nombres);

// 5. FONCTION QUI RETOURNE UNE FONCTION
function creerMultiplicateur($facteur) {
    return function($nombre) use ($facteur) {
        return $nombre * $facteur;
    };
}

$double = creerMultiplicateur(2);
$triple = creerMultiplicateur(3);

echo $double(5); // 10
echo $triple(5); // 15

// 6. CALLBACK FUNCTIONS
function traiterTableau(array $tableau, callable $callback) {
    $resultat = [];
    foreach ($tableau as $element) {
        $resultat[] = $callback($element);
    }
    return $resultat;
}

$nombres = [1, 2, 3, 4];

// Avec fonction anonyme
$doubles = traiterTableau($nombres, function($n) {
    return $n * 2;
});

// Avec arrow function
$carres = traiterTableau($nombres, fn($n) => $n ** 2);

// 7. FONCTIONS D'ORDRE SUPÉRIEUR
function compose(callable $f, callable $g) {
    return function($x) use ($f, $g) {
        return $f($g($x));
    };
}

$addOne = fn($x) => $x + 1;
$double = fn($x) => $x * 2;

$addOneThenDouble = compose($double, $addOne);
echo $addOneThenDouble(5); // (5 + 1) * 2 = 12

// 8. MEMOIZATION AVEC CLOSURES
function memoize(callable $func) {
    $cache = [];
    
    return function(...$args) use ($func, &$cache) {
        $key = serialize($args);
        
        if (!isset($cache[$key])) {
            $cache[$key] = $func(...$args);
        }
        
        return $cache[$key];
    };
}

// Fibonacci avec memoization
$fibonacci = memoize(function($n) use (&$fibonacci) {
    if ($n <= 1) return $n;
    return $fibonacci($n - 1) + $fibonacci($n - 2);
});

echo $fibonacci(40); // Très rapide grâce au cache

// 9. EVENT LISTENERS AVEC CLOSURES
class EventEmitter {
    private $listeners = [];
    
    public function on($event, callable $callback) {
        $this->listeners[$event][] = $callback;
    }
    
    public function emit($event, ...$args) {
        if (isset($this->listeners[$event])) {
            foreach ($this->listeners[$event] as $callback) {
                $callback(...$args);
            }
        }
    }
}

$emitter = new EventEmitter();

// Ajout d'listeners avec closures
$emitter->on('user.login', function($user) {
    echo "Utilisateur connecté: " . $user['nom'];
});

$emitter->on('user.login', function($user) {
    // Log dans un fichier
    file_put_contents('login.log', date('Y-m-d H:i:s') . " - " . $user['nom'] . "\n", FILE_APPEND);
});

$emitter->emit('user.login', ['nom' => 'Alice']);

// 10. FACTORY PATTERN AVEC CLOSURES
function createValidator() {
    $rules = [];
    
    return [
        'addRule' => function($field, callable $rule) use (&$rules) {
            $rules[$field][] = $rule;
        },
        'validate' => function($data) use (&$rules) {
            $errors = [];
            foreach ($rules as $field => $fieldRules) {
                if (isset($data[$field])) {
                    foreach ($fieldRules as $rule) {
                        $result = $rule($data[$field]);
                        if ($result !== true) {
                            $errors[$field][] = $result;
                        }
                    }
                }
            }
            return $errors;
        }
    ];
}

$validator = createValidator();

$validator['addRule']('email', function($value) {
    return filter_var($value, FILTER_VALIDATE_EMAIL) ? true : 'Email invalide';
});

$validator['addRule']('age', function($value) {
    return ($value >= 18) ? true : 'Doit être majeur';
});

$errors = $validator['validate']([
    'email' => 'invalid-email',
    'age' => 16
]);

print_r($errors);

// 11. CURRYING (FONCTIONS PARTIELLES)
function curry(callable $func, int $arity = null) {
    $arity = $arity ?? (new ReflectionFunction($func))->getNumberOfParameters();
    
    return function(...$args) use ($func, $arity) {
        if (count($args) >= $arity) {
            return $func(...$args);
        }
        
        return curry(function(...$nextArgs) use ($func, $args) {
            return $func(...array_merge($args, $nextArgs));
        }, $arity - count($args));
    };
}

$add = curry(function($a, $b, $c) {
    return $a + $b + $c;
});

$add5 = $add(5);
$add5and3 = $add5(3);
echo $add5and3(2); // 10

Fonctions Récursives

Comprenez la récursivité avec des exemples pratiques et des optimisations.

🔄 Récursivité : Théorie et Pratique

<?php
// FONCTIONS RÉCURSIVES : EXEMPLES ET OPTIMISATIONS

// 1. FACTORIELLE (EXEMPLE CLASSIQUE)
function factorielle($n) {
    // Cas de base (condition d'arrêt)
    if ($n <= 1) {
        return 1;
    }
    
    // Appel récursif
    return $n * factorielle($n - 1);
}

echo factorielle(5); // 120 (5 * 4 * 3 * 2 * 1)

// 2. FIBONACCI (VERSION NAÏVE)
function fibonacci($n) {
    if ($n <= 1) {
        return $n;
    }
    
    return fibonacci($n - 1) + fibonacci($n - 2);
}

echo fibonacci(10); // 55 (mais très lent pour grandes valeurs)

// 3. FIBONACCI OPTIMISÉ AVEC MEMOIZATION
function fibonacciMemo($n, &$cache = []) {
    if ($n <= 1) {
        return $n;
    }
    
    if (isset($cache[$n])) {
        return $cache[$n];
    }
    
    $cache[$n] = fibonacciMemo($n - 1, $cache) + fibonacciMemo($n - 2, $cache);
    return $cache[$n];
}

echo fibonacciMemo(50); // Beaucoup plus rapide !

// 4. PARCOURS D'ARBORESCENCE
function parcourirDossier($chemin, $niveau = 0) {
    $resultat = [];
    $indentation = str_repeat("  ", $niveau);
    
    if (is_dir($chemin)) {
        $resultat[] = $indentation . "📁 " . basename($chemin);
        
        $fichiers = scandir($chemin);
        foreach ($fichiers as $fichier) {
            if ($fichier !== '.' && $fichier !== '..') {
                $cheminComplet = $chemin . DIRECTORY_SEPARATOR . $fichier;
                
                if (is_dir($cheminComplet)) {
                    // Appel récursif pour les sous-dossiers
                    $resultat = array_merge($resultat, parcourirDossier($cheminComplet, $niveau + 1));
                } else {
                    $resultat[] = $indentation . "  📄 " . $fichier;
                }
            }
        }
    }
    
    return $resultat;
}

// Utilisation
$arborescence = parcourirDossier('/chemin/vers/dossier');
foreach ($arborescence as $element) {
    echo $element . "\n";
}

// 5. CALCUL DE PUISSANCE
function puissance($base, $exposant) {
    // Cas de base
    if ($exposant === 0) {
        return 1;
    }
    
    if ($exposant === 1) {
        return $base;
    }
    
    // Optimisation : division de l'exposant par 2
    if ($exposant % 2 === 0) {
        $temp = puissance($base, $exposant / 2);
        return $temp * $temp;
    } else {
        return $base * puissance($base, $exposant - 1);
    }
}

echo puissance(2, 10); // 1024

// 6. RECHERCHE BINAIRE RÉCURSIVE
function rechercheBinaire($tableau, $valeur, $debut = 0, $fin = null) {
    if ($fin === null) {
        $fin = count($tableau) - 1;
    }
    
    // Cas de base : élément non trouvé
    if ($debut > $fin) {
        return -1;
    }
    
    $milieu = intval(($debut + $fin) / 2);
    
    // Cas de base : élément trouvé
    if ($tableau[$milieu] === $valeur) {
        return $milieu;
    }
    
    // Récursion sur la moitié appropriée
    if ($tableau[$milieu] > $valeur) {
        return rechercheBinaire($tableau, $valeur, $debut, $milieu - 1);
    } else {
        return rechercheBinaire($tableau, $valeur, $milieu + 1, $fin);
    }
}

$tableauTrie = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
echo rechercheBinaire($tableauTrie, 7); // Position 3

// 7. GÉNÉRATION DE PERMUTATIONS
function genererPermutations($elements) {
    // Cas de base
    if (count($elements) <= 1) {
        return [$elements];
    }
    
    $permutations = [];
    
    for ($i = 0; $i < count($elements); $i++) {
        // Élément actuel
        $elementActuel = $elements[$i];
        
        // Éléments restants
        $elementsRestants = array_merge(
            array_slice($elements, 0, $i),
            array_slice($elements, $i + 1)
        );
        
        // Générer permutations pour les éléments restants
        $permutationsRestantes = genererPermutations($elementsRestants);
        
        // Ajouter l'élément actuel à chaque permutation
        foreach ($permutationsRestantes as $permutation) {
            $permutations[] = array_merge([$elementActuel], $permutation);
        }
    }
    
    return $permutations;
}

$permutations = genererPermutations(['A', 'B', 'C']);
foreach ($permutations as $perm) {
    echo implode('', $perm) . " ";
}
// Affiche: ABC ACB BAC BCA CAB CBA

// 8. ALGORITHME DU TRI RAPIDE (QUICKSORT)
function triRapide($tableau) {
    $longueur = count($tableau);
    
    // Cas de base
    if ($longueur <= 1) {
        return $tableau;
    }
    
    // Choisir un pivot (ici le premier élément)
    $pivot = $tableau[0];
    $gauche = [];
    $droite = [];
    
    // Partitionner autour du pivot
    for ($i = 1; $i < $longueur; $i++) {
        if ($tableau[$i] <= $pivot) {
            $gauche[] = $tableau[$i];
        } else {
            $droite[] = $tableau[$i];
        }
    }
    
    // Récursion et combinaison
    return array_merge(
        triRapide($gauche),
        [$pivot],
        triRapide($droite)
    );
}

$tableauDesordonne = [64, 34, 25, 12, 22, 11, 90];
$tableauTrie = triRapide($tableauDesordonne);
print_r($tableauTrie);

// 9. VALIDATION D'EXPRESSION PARENTHÉSÉE
function validerParentheses($expression, $index = 0, $compteur = 0) {
    // Cas de base : fin de chaîne
    if ($index >= strlen($expression)) {
        return $compteur === 0;
    }
    
    $caractere = $expression[$index];
    
    if ($caractere === '(') {
        $compteur++;
    } elseif ($caractere === ')') {
        $compteur--;
        
        // Si compteur négatif, parenthèse fermante sans ouvrante
        if ($compteur < 0) {
            return false;
        }
    }
    
    // Récursion pour le caractère suivant
    return validerParentheses($expression, $index + 1, $compteur);
}

echo validerParentheses("((()))") ? "Valide" : "Invalide"; // Valide
echo validerParentheses("((())") ? "Valide" : "Invalide"; // Invalide

// 10. CONVERSION D'ITERATION EN RÉCURSION
class RecursionHelper {
    
    // Version itérative de la somme
    public static function sommeIterative($n) {
        $somme = 0;
        for ($i = 1; $i <= $n; $i++) {
            $somme += $i;
        }
        return $somme;
    }
    
    // Version récursive de la somme
    public static function sommeRecursive($n) {
        if ($n <= 0) {
            return 0;
        }
        return $n + self::sommeRecursive($n - 1);
    }
    
    // Optimisation avec récursion terminale
    public static function sommeRecursiveOptimisee($n, $accumulator = 0) {
        if ($n <= 0) {
            return $accumulator;
        }
        return self::sommeRecursiveOptimisee($n - 1, $accumulator + $n);
    }
}

echo RecursionHelper::sommeIterative(100); // 5050
echo RecursionHelper::sommeRecursive(100); // 5050
echo RecursionHelper::sommeRecursiveOptimisee(100); // 5050 (plus efficace)

// 11. GESTION DES ERREURS EN RÉCURSION
function factorielleSecurisee($n, $maxDepth = 100, $currentDepth = 0) {
    // Vérification de la profondeur pour éviter stack overflow
    if ($currentDepth > $maxDepth) {
        throw new RuntimeException("Profondeur de récursion dépassée");
    }
    
    // Validation des paramètres
    if (!is_int($n) || $n < 0) {
        throw new InvalidArgumentException("Doit être un entier positif");
    }
    
    // Cas de base
    if ($n <= 1) {
        return 1;
    }
    
    // Récursion avec compteur de profondeur
    return $n * factorielleSecurisee($n - 1, $maxDepth, $currentDepth + 1);
}

try {
    echo factorielleSecurisee(5); // 120
    echo factorielleSecurisee(-1); // Exception
} catch (Exception $e) {
    echo "Erreur: " . $e->getMessage();
}
?>

Concepts Avancés

Découvrez les concepts avancés : générateurs, réflexion, et patterns de programmation fonctionnelle.

🚀 Générateurs et Concepts Avancés

<?php
// CONCEPTS AVANCÉS DES FONCTIONS PHP

// 1. GÉNÉRATEURS (YIELD)
function genererNombres($max) {
    for ($i = 1; $i <= $max; $i++) {
        yield $i; // Génère une valeur à la demande
    }
}

// Utilisation : économise la mémoire
foreach (genererNombres(1000000) as $nombre) {
    if ($nombre > 5) break;
    echo $nombre . " ";
}

// 2. GÉNÉRATEUR AVEC CLÉS
function genererPaires() {
    yield 'nom' => 'Alice';
    yield 'age' => 25;
    yield 'ville' => 'Paris';
}

foreach (genererPaires() as $cle => $valeur) {
    echo "$cle: $valeur\n";
}

// 3. RÉFLEXION SUR LES FONCTIONS
function exempleFunction($param1, $param2 = 'default') {
    return $param1 . $param2;
}

$reflection = new ReflectionFunction('exempleFunction');
echo "Nom: " . $reflection->getName();
echo "Nombre de paramètres: " . $reflection->getNumberOfParameters();
echo "Fichier: " . $reflection->getFileName();

foreach ($reflection->getParameters() as $param) {
    echo "Paramètre: " . $param->getName();
    if ($param->isDefaultValueAvailable()) {
        echo " (défaut: " . $param->getDefaultValue() . ")";
    }
}

// 4. FONCTIONS VARIABLES
$nomFonction = 'strlen';
echo $nomFonction('Hello'); // Appelle strlen('Hello')

// Avec vérification
if (function_exists($nomFonction)) {
    echo $nomFonction('World');
}

// 5. CALL_USER_FUNC ET VARIANTES
call_user_func('phpinfo'); // Appelle phpinfo()
call_user_func_array('array_merge', [['a'], ['b']]); // array_merge(['a'], ['b'])

// Avec objets
class Calculator {
    public function add($a, $b) {
        return $a + $b;
    }
}

$calc = new Calculator();
echo call_user_func([$calc, 'add'], 5, 3); // 8

// 6. DESIGN PATTERN: STRATEGY AVEC FUNCTIONS
class PaymentProcessor {
    private $strategies = [];
    
    public function addStrategy($name, callable $strategy) {
        $this->strategies[$name] = $strategy;
    }
    
    public function process($method, $amount) {
        if (!isset($this->strategies[$method])) {
            throw new InvalidArgumentException("Méthode de paiement inconnue");
        }
        
        return $this->strategies[$method]($amount);
    }
}

$processor = new PaymentProcessor();

$processor->addStrategy('carte', function($amount) {
    return "Paiement de {$amount}€ par carte (commission: 2%)";
});

$processor->addStrategy('paypal', function($amount) {
    return "Paiement de {$amount}€ via PayPal (commission: 3%)";
});

echo $processor->process('carte', 100);

// 7. MIDDLEWARE PATTERN
class MiddlewareStack {
    private $middlewares = [];
    
    public function add(callable $middleware) {
        $this->middlewares[] = $middleware;
    }
    
    public function execute($request) {
        $response = $request;
        
        foreach ($this->middlewares as $middleware) {
            $response = $middleware($response);
        }
        
        return $response;
    }
}

$stack = new MiddlewareStack();

$stack->add(function($request) {
    $request['timestamp'] = time();
    return $request;
});

$stack->add(function($request) {
    $request['processed'] = true;
    return $request;
});

$result = $stack->execute(['data' => 'test']);
print_r($result);

// 8. FUNCTION COMPOSITION AVANCÉE
function pipe(...$functions) {
    return function($value) use ($functions) {
        return array_reduce($functions, function($carry, $func) {
            return $func($carry);
        }, $value);
    };
}

$pipeline = pipe(
    fn($x) => $x * 2,
    fn($x) => $x + 10,
    fn($x) => $x / 3
);

echo $pipeline(5); // ((5 * 2) + 10) / 3 = 6.67

// 9. LAZY EVALUATION
class LazyValue {
    private $computed = false;
    private $value;
    private $computation;
    
    public function __construct(callable $computation) {
        $this->computation = $computation;
    }
    
    public function get() {
        if (!$this->computed) {
            $this->value = ($this->computation)();
            $this->computed = true;
        }
        return $this->value;
    }
}

$lazy = new LazyValue(function() {
    echo "Calcul coûteux exécuté\n";
    return array_sum(range(1, 1000000));
});

// Le calcul n'est pas encore exécuté
echo "Avant get()\n";
echo $lazy->get(); // Maintenant le calcul s'exécute
echo $lazy->get(); // Utilise la valeur mise en cache

// 10. FUNCTION DECORATORS
function benchmark(callable $func) {
    return function(...$args) use ($func) {
        $start = microtime(true);
        $result = $func(...$args);
        $end = microtime(true);
        
        echo "Execution time: " . ($end - $start) . " seconds\n";
        return $result;
    };
}

function cache(callable $func) {
    $cache = [];
    
    return function(...$args) use ($func, &$cache) {
        $key = serialize($args);
        
        if (!isset($cache[$key])) {
            $cache[$key] = $func(...$args);
        }
        
        return $cache[$key];
    };
}

// Décorer une fonction
$slowFunction = function($n) {
    usleep(100000); // Simule une opération lente
    return $n * $n;
};

$cachedFunction = cache($slowFunction);
$benchmarkedFunction = benchmark($cachedFunction);

echo $benchmarkedFunction(5); // Lent la première fois
echo $benchmarkedFunction(5); // Rapide la deuxième fois (cache)
?>

Exemples Pratiques à Copier

Fonctions utiles et prêtes à l'emploi pour vos projets PHP.

🛠️ Fonctions Utilitaires Pratiques

<?php
// CONCEPTS AVANCÉS DES FONCTIONS PHP

// 1. GÉNÉRATEURS (YIELD)
function genererNombres($max) {
    for ($i = 1; $i <= $max; $i++) {
        yield $i; // Génère une valeur à la demande
    }
}

// Utilisation : économise la mémoire
foreach (genererNombres(1000000) as $nombre) {
    if ($nombre > 5) break;
    echo $nombre . " ";
}

// 2. GÉNÉRATEUR AVEC CLÉS
function genererPaires() {
    yield 'nom' => 'Alice';
    yield 'age' => 25;
    yield 'ville' => 'Paris';
}

foreach (genererPaires() as $cle => $valeur) {
    echo "$cle: $valeur\n";
}

// 3. RÉFLEXION SUR LES FONCTIONS
function exempleFunction($param1, $param2 = 'default') {
    return $param1 . $param2;
}

$reflection = new ReflectionFunction('exempleFunction');
echo "Nom: " . $reflection->getName();
echo "Nombre de paramètres: " . $reflection->getNumberOfParameters();
echo "Fichier: " . $reflection->getFileName();

foreach ($reflection->getParameters() as $param) {
    echo "Paramètre: " . $param->getName();
    if ($param->isDefaultValueAvailable()) {
        echo " (défaut: " . $param->getDefaultValue() . ")";
    }
}

// 4. FONCTIONS VARIABLES
$nomFonction = 'strlen';
echo $nomFonction('Hello'); // Appelle strlen('Hello')

// Avec vérification
if (function_exists($nomFonction)) {
    echo $nomFonction('World');
}

// 5. CALL_USER_FUNC ET VARIANTES
call_user_func('phpinfo'); // Appelle phpinfo()
call_user_func_array('array_merge', [['a'], ['b']]); // array_merge(['a'], ['b'])

// Avec objets
class Calculator {
    public function add($a, $b) {
        return $a + $b;
    }
}

$calc = new Calculator();
echo call_user_func([$calc, 'add'], 5, 3); // 8

// 6. DESIGN PATTERN: STRATEGY AVEC FUNCTIONS
class PaymentProcessor {
    private $strategies = [];
    
    public function addStrategy($name, callable $strategy) {
        $this->strategies[$name] = $strategy;
    }
    
    public function process($method, $amount) {
        if (!isset($this->strategies[$method])) {
            throw new InvalidArgumentException("Méthode de paiement inconnue");
        }
        
        return $this->strategies[$method]($amount);
    }
}

$processor = new PaymentProcessor();

$processor->addStrategy('carte', function($amount) {
    return "Paiement de {$amount}€ par carte (commission: 2%)";
});

$processor->addStrategy('paypal', function($amount) {
    return "Paiement de {$amount}€ via PayPal (commission: 3%)";
});

echo $processor->process('carte', 100);

// 7. MIDDLEWARE PATTERN
class MiddlewareStack {
    private $middlewares = [];
    
    public function add(callable $middleware) {
        $this->middlewares[] = $middleware;
    }
    
    public function execute($request) {
        $response = $request;
        
        foreach ($this->middlewares as $middleware) {
            $response = $middleware($response);
        }
        
        return $response;
    }
}

$stack = new MiddlewareStack();

$stack->add(function($request) {
    $request['timestamp'] = time();
    return $request;
});

$stack->add(function($request) {
    $request['processed'] = true;
    return $request;
});

$result = $stack->execute(['data' => 'test']);
print_r($result);

// 8. FUNCTION COMPOSITION AVANCÉE
function pipe(...$functions) {
    return function($value) use ($functions) {
        return array_reduce($functions, function($carry, $func) {
            return $func($carry);
        }, $value);
    };
}

$pipeline = pipe(
    fn($x) => $x * 2,
    fn($x) => $x + 10,
    fn($x) => $x / 3
);

echo $pipeline(5); // ((5 * 2) + 10) / 3 = 6.67

// 9. LAZY EVALUATION
class LazyValue {
    private $computed = false;
    private $value;
    private $computation;
    
    public function __construct(callable $computation) {
        $this->computation = $computation;
    }
    
    public function get() {
        if (!$this->computed) {
            $this->value = ($this->computation)();
            $this->computed = true;
        }
        return $this->value;
    }
}

$lazy = new LazyValue(function() {
    echo "Calcul coûteux exécuté\n";
    return array_sum(range(1, 1000000));
});

// Le calcul n'est pas encore exécuté
echo "Avant get()\n";
echo $lazy->get(); // Maintenant le calcul s'exécute
echo $lazy->get(); // Utilise la valeur mise en cache

// 10. FUNCTION DECORATORS
function benchmark(callable $func) {
    return function(...$args) use ($func) {
        $start = microtime(true);
        $result = $func(...$args);
        $end = microtime(true);
        
        echo "Execution time: " . ($end - $start) . " seconds\n";
        return $result;
    };
}

function cache(callable $func) {
    $cache = [];
    
    return function(...$args) use ($func, &$cache) {
        $key = serialize($args);
        
        if (!isset($cache[$key])) {
            $cache[$key] = $func(...$args);
        }
        
        return $cache[$key];
    };
}

// Décorer une fonction
$slowFunction = function($n) {
    usleep(100000); // Simule une opération lente
    return $n * $n;
};

$cachedFunction = cache($slowFunction);
$benchmarkedFunction = benchmark($cachedFunction);

echo $benchmarkedFunction(5); // Lent la première fois
echo $benchmarkedFunction(5); // Rapide la deuxième fois (cache)
?>

Meilleures Pratiques pour les Fonctions PHP

✅ À FAIRE :

Utiliser des noms de fonctions descriptifs
Limiter les fonctions à une seule responsabilité
Utiliser le typage strict (declare(strict_types=1))
Documenter avec PHPDoc
Valider les paramètres d'entrée
Gérer les erreurs avec des exceptions
Préférer la composition à l'héritage

❌ À ÉVITER :

Fonctions trop longues (plus de 20-30 lignes)
Trop de paramètres (plus de 3-4)
Effets de bord non documentés
Variables globales dans les fonctions
Récursion sans limite de profondeur
Mélanger logique métier et présentation
Ignorer les valeurs de retour des fonctions

Fonctions PHP Maîtrisées !

Vous maîtrisez maintenant tous les aspects des fonctions PHP : création, natives, récursivité, closures et concepts avancés. Passez au niveau supérieur !

🎯 Compétences acquises :

Syntaxe Fonctions • Paramètres Avancés • Fonctions Natives • Closures • Récursivité • Générateurs • Concepts Avancés