Programmation PHP

Tableaux PHP

Maîtrisez les tableaux PHP de A à Z : création, manipulation, fonctions natives, tableaux multidimensionnels et concepts avancés pour structurer vos données efficacement.

📊 Indexés
🗝️ Associatifs
📋 Multidimensionnels
⚡ Fonctions

Bases des Tableaux PHP

Comprendre ce qu'est un tableau, les différents types et leur utilisation.

📊 Qu'est-ce qu'un Tableau ?

Concept et Types :

📋 Définition :

Un tableau est une structure de données qui permet de stocker plusieurs valeurs dans une seule variable. PHP propose des tableaux très flexibles.

🏷️ Types de tableaux :
  • Indexés : indices numériques (0, 1, 2...)
  • Associatifs : clés personnalisées
  • Multidimensionnels : tableaux de tableaux

Syntaxes de création :

// Syntaxe moderne (PHP 5.4+)
$fruits = ['pomme', 'banane', 'orange'];
// Syntaxe classique
$fruits = array('pomme', 'banane', 'orange');
// Tableau associatif
$personne = [
'nom' => 'Dupont',
'age' => 30
];

🏷️ Types de Tableaux en Détail

<?php
// 1. TABLEAUX INDEXÉS (NUMÉRIQUES)
$couleurs = ['rouge', 'vert', 'bleu'];
echo $couleurs[0]; // rouge
echo $couleurs[1]; // vert

// Indices automatiques
$nombres = [];
$nombres[] = 10; // index 0
$nombres[] = 20; // index 1
$nombres[] = 30; // index 2

// Indices explicites
$notes = [
    0 => 15,
    1 => 12,
    2 => 18
];

// 2. TABLEAUX ASSOCIATIFS (CLÉS PERSONNALISÉES)
$utilisateur = [
    'nom' => 'Dupont',
    'prenom' => 'Jean',
    'age' => 25,
    'email' => 'jean.dupont@email.com',
    'actif' => true
];

echo $utilisateur['nom']; // Dupont
echo $utilisateur['age']; // 25

// Configuration d'application
$config = [
    'database' => [
        'host' => 'localhost',
        'user' => 'root',
        'password' => 'secret'
    ],
    'app' => [
        'name' => 'Mon App',
        'version' => '1.0'
    ]
];

// 3. TABLEAUX MIXTES (INDICES ET CLÉS)
$mixte = [
    0 => 'première valeur',
    'nom' => 'John',
    1 => 'deuxième valeur',
    'age' => 30
];

// 4. TABLEAUX MULTIDIMENSIONNELS
$etudiants = [
    [
        'nom' => 'Alice',
        'notes' => [15, 17, 12]
    ],
    [
        'nom' => 'Bob',
        'notes' => [18, 16, 14]
    ]
];

echo $etudiants[0]['nom']; // Alice
echo $etudiants[0]['notes'][1]; // 17

// 5. TABLEAUX D'OBJETS
class Produit {
    public function __construct(public $nom, public $prix) {}
}

$produits = [
    new Produit('Ordinateur', 999),
    new Produit('Souris', 25),
    new Produit('Clavier', 75)
];

foreach ($produits as $produit) {
    echo $produit->nom . ' : ' . $produit->prix . '€';
}

// 6. TABLEAUX CONSTANTS
const JOURS_SEMAINE = ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi'];
define('COULEURS', ['rouge', 'vert', 'bleu']);

// 7. VÉRIFICATION DU TYPE
var_dump(is_array($couleurs)); // true
var_dump(array_is_list($couleurs)); // true (PHP 8.1+)
var_dump(array_is_list($utilisateur)); // false

// 8. INFORMATIONS SUR LES TABLEAUX
echo count($couleurs); // 3
echo sizeof($utilisateur); // 5 (alias de count)
var_dump(empty($couleurs)); // false

// Taille récursive (tableaux multidimensionnels)
echo count($etudiants, COUNT_RECURSIVE); // Compte tous les éléments

// 9. ACCÈS AUX ÉLÉMENTS
// Avec vérification d'existence
$nom = isset($utilisateur['nom']) ? $utilisateur['nom'] : 'Inconnu';

// Opérateur null coalescing (PHP 7+)
$nom = $utilisateur['nom'] ?? 'Inconnu';

// Accès avec clé dynamique
$cle = 'age';
echo $utilisateur[$cle]; // 25
?>

Création et Manipulation

Apprenez à créer, modifier et manipuler efficacement vos tableaux PHP.

🛠️ Techniques de Création Avancées

<?php
// 1. CRÉATION AVEC RANGE
$nombres = range(1, 10); // [1, 2, 3, ..., 10]
$lettres = range('a', 'z'); // ['a', 'b', 'c', ..., 'z']
$pairs = range(0, 20, 2); // [0, 2, 4, 6, ..., 20]

// 2. ARRAY_FILL ET ARRAY_FILL_KEYS
$zeros = array_fill(0, 5, 0); // [0, 0, 0, 0, 0]
$defaut = array_fill(10, 3, 'vide'); // [10 => 'vide', 11 => 'vide', 12 => 'vide']

$cles = ['nom', 'email', 'age'];
$formulaire = array_fill_keys($cles, ''); 
// ['nom' => '', 'email' => '', 'age' => '']

// 3. ARRAY_COMBINE
$prenoms = ['Alice', 'Bob', 'Charlie'];
$ages = [25, 30, 35];
$personnes = array_combine($prenoms, $ages);
// ['Alice' => 25, 'Bob' => 30, 'Charlie' => 35]

// 4. EXPLODE ET IMPLODE
$csv = "pomme,banane,orange,kiwi";
$fruits = explode(',', $csv); // ['pomme', 'banane', 'orange', 'kiwi']

$liste = implode(' | ', $fruits); // "pomme | banane | orange | kiwi"
$json_like = implode(', ', $fruits); // "pomme, banane, orange, kiwi"

// 5. AJOUT ET SUPPRESSION D'ÉLÉMENTS
$stack = ['a', 'b'];

// Ajout à la fin
array_push($stack, 'c', 'd'); // ['a', 'b', 'c', 'd']
$stack[] = 'e'; // Plus rapide pour un élément

// Ajout au début
array_unshift($stack, 'START'); // ['START', 'a', 'b', 'c', 'd', 'e']

// Suppression de la fin
$dernier = array_pop($stack); // 'e'

// Suppression du début
$premier = array_shift($stack); // 'START'

// 6. INSERTION ET SUPPRESSION À UNE POSITION
$arr = ['a', 'b', 'd', 'e'];

// Insérer 'c' à la position 2
array_splice($arr, 2, 0, 'c'); // ['a', 'b', 'c', 'd', 'e']

// Remplacer 1 élément à la position 1
array_splice($arr, 1, 1, ['B', 'BB']); // ['a', 'B', 'BB', 'c', 'd', 'e']

// 7. FUSION DE TABLEAUX
$arr1 = ['a', 'b'];
$arr2 = ['c', 'd'];
$arr3 = ['e', 'f'];

// Fusion simple
$fusion = array_merge($arr1, $arr2, $arr3); // ['a', 'b', 'c', 'd', 'e', 'f']

// Spread operator (PHP 7.4+)
$fusion2 = [...$arr1, ...$arr2, ...$arr3]; // Même résultat, plus rapide

// Fusion récursive pour tableaux associatifs
$config1 = ['db' => ['host' => 'localhost'], 'app' => ['debug' => true]];
$config2 = ['db' => ['port' => 3306], 'app' => ['name' => 'MonApp']];
$config = array_merge_recursive($config1, $config2);

// 8. MODIFICATION PAR RÉFÉRENCE
$original = [1, 2, 3];
$copie = $original; // Copie
$reference = &$original; // Référence

$original[0] = 99;
print_r($copie); // [1, 2, 3] - inchangé
print_r($reference); // [99, 2, 3] - modifié

// 9. CLONAGE DE TABLEAUX MULTIDIMENSIONNELS
function clonageProf($array) {
    $clone = [];
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            $clone[$key] = clonageProf($value);
        } else {
            $clone[$key] = $value;
        }
    }
    return $clone;
}

// Ou avec serialize/unserialize (attention aux objets)
$clone_rapide = unserialize(serialize($tableau_complexe));

// 10. CRÉATION CONDITIONNELLE
$user_data = [];
$user_data['nom'] = $nom ?? 'Anonyme';
$user_data['age'] = $age > 0 ? $age : null;

// Création avec conditions
$options = array_filter([
    'debug' => $debug_mode ? true : null,
    'cache' => $enable_cache ? 3600 : null,
    'log_level' => $log_level ?: null
], function($value) {
    return $value !== null;
});
?>

Fonctions Natives Essentielles

Découvrez les fonctions PHP les plus utiles pour manipuler et traiter vos tableaux.

🔍 Recherche et Filtrage

<?php
// RECHERCHE ET FILTRAGE DANS LES TABLEAUX

$fruits = ['pomme', 'banane', 'orange', 'kiwi', 'pomme'];
$notes = [12, 15, 8, 20, 14, 18];
$users = [
    ['nom' => 'Alice', 'age' => 25, 'actif' => true],
    ['nom' => 'Bob', 'age' => 30, 'actif' => false],
    ['nom' => 'Charlie', 'age' => 20, 'actif' => true]
];

// 1. IN_ARRAY - Vérifier si une valeur existe
if (in_array('banane', $fruits)) {
    echo "Banane trouvée !";
}

// Recherche stricte (type et valeur)
var_dump(in_array(12, $notes)); // true
var_dump(in_array('12', $notes, true)); // false (strict)

// 2. ARRAY_SEARCH - Trouver la clé d'une valeur
$position = array_search('orange', $fruits);
if ($position !== false) {
    echo "Orange trouvée à la position: " . $position; // 2
}

// Recherche de toutes les occurrences
$positions_pomme = array_keys($fruits, 'pomme'); // [0, 4]

// 3. ARRAY_KEY_EXISTS - Vérifier si une clé existe
$config = ['debug' => false, 'cache' => null];

if (array_key_exists('debug', $config)) {
    echo "Clé 'debug' existe"; // S'exécute même si valeur = false
}

// Différence avec isset()
var_dump(isset($config['cache'])); // false (car null)
var_dump(array_key_exists('cache', $config)); // true

// 4. ARRAY_FILTER - Filtrer les éléments
// Supprimer les valeurs vides/nulles
$data = ['nom', '', 'email', null, 'age', 0];
$clean = array_filter($data); // ['nom', 'email', 'age']

// Filtrer avec fonction personnalisée
$bonnes_notes = array_filter($notes, function($note) {
    return $note >= 15;
}); // [15, 20, 18]

// Filtrer avec arrow function (PHP 7.4+)
$adultes = array_filter($users, fn($user) => $user['age'] >= 25);

// Filtrer les clés
$user = ['nom' => 'John', 'password' => 'secret', 'email' => 'john@test.com'];
$public_data = array_filter($user, function($key) {
    return $key !== 'password';
}, ARRAY_FILTER_USE_KEY);

// Filtrer avec clé ET valeur
$filtered = array_filter($user, function($value, $key) {
    return $key !== 'password' && !empty($value);
}, ARRAY_FILTER_USE_BOTH);

// 5. ARRAY_COLUMN - Extraire une colonne
$noms = array_column($users, 'nom'); // ['Alice', 'Bob', 'Charlie']

// Avec clé d'index
$users_by_name = array_column($users, 'age', 'nom');
// ['Alice' => 25, 'Bob' => 30, 'Charlie' => 20]

// Extraire objets complets avec nouvelle clé
$users_indexed = array_column($users, null, 'nom');

// 6. ARRAY_UNIQUE - Supprimer les doublons
$colors = ['rouge', 'bleu', 'rouge', 'vert', 'bleu'];
$unique_colors = array_unique($colors); // ['rouge', 'bleu', 'vert']

// Préserver les clés originales
print_r($unique_colors); // [0 => 'rouge', 1 => 'bleu', 3 => 'vert']

// Réindexer
$reindexed = array_values(array_unique($colors));

// 7. ARRAY_DIFF ET ARRAY_INTERSECT
$array1 = ['a', 'b', 'c', 'd'];
$array2 = ['b', 'c', 'e', 'f'];

// Différence (éléments de $array1 pas dans $array2)
$diff = array_diff($array1, $array2); // ['a', 'd']

// Intersection (éléments communs)
$intersect = array_intersect($array1, $array2); // ['b', 'c']

// Différence sur les clés
$assoc1 = ['a' => 1, 'b' => 2, 'c' => 3];
$assoc2 = ['b' => 2, 'c' => 4, 'd' => 5];

$diff_keys = array_diff_key($assoc1, $assoc2); // ['a' => 1]
$diff_assoc = array_diff_assoc($assoc1, $assoc2); // ['a' => 1, 'c' => 3]

// 8. FONCTIONS AVANCÉES DE RECHERCHE
function rechercheAvancee($array, $criteres) {
    return array_filter($array, function($item) use ($criteres) {
        foreach ($criteres as $key => $value) {
            if (!isset($item[$key]) || $item[$key] !== $value) {
                return false;
            }
        }
        return true;
    });
}

$users_actifs = rechercheAvancee($users, ['actif' => true]);

// Recherche floue
function rechercheFloue($array, $terme, $champ = null) {
    return array_filter($array, function($item) use ($terme, $champ) {
        $texte = $champ ? $item[$champ] : $item;
        return stripos($texte, $terme) !== false;
    });
}

$resultats = rechercheFloue($users, 'al', 'nom'); // Trouve "Alice" et "Charlie"
?>

🔄 Tri et Transformation

<?php
// TRI ET TRANSFORMATION DE TABLEAUX

$nombres = [3, 1, 4, 1, 5, 9, 2];
$fruits = ['banane', 'pomme', 'orange'];
$users = [
    ['nom' => 'Alice', 'age' => 25, 'score' => 95],
    ['nom' => 'Bob', 'age' => 30, 'score' => 87],
    ['nom' => 'Charlie', 'age' => 20, 'score' => 92]
];

// 1. TRI SIMPLE
// sort() - Tri croissant (réindexe les clés)
$nombres_copies = $nombres;
sort($nombres_copies); // [1, 1, 2, 3, 4, 5, 9]

// rsort() - Tri décroissant
$nombres_desc = $nombres;
rsort($nombres_desc); // [9, 5, 4, 3, 2, 1, 1]

// 2. TRI AVEC PRÉSERVATION DES CLÉS
$assoc = ['c' => 3, 'a' => 1, 'b' => 2];

// asort() - Tri par valeurs (garde les clés)
$by_values = $assoc;
asort($by_values); // ['a' => 1, 'b' => 2, 'c' => 3]

// arsort() - Tri décroissant par valeurs
$by_values_desc = $assoc;
arsort($by_values_desc); // ['c' => 3, 'b' => 2, 'a' => 1]

// ksort() - Tri par clés
$by_keys = $assoc;
ksort($by_keys); // ['a' => 1, 'b' => 2, 'c' => 3]

// krsort() - Tri décroissant par clés
$by_keys_desc = $assoc;
krsort($by_keys_desc); // ['c' => 3, 'b' => 2, 'a' => 1]

// 3. TRI PERSONNALISÉ AVEC USORT
// Tri par âge
$users_by_age = $users;
usort($users_by_age, function($a, $b) {
    return $a['age'] <=> $b['age'];
});

// Tri par score décroissant avec arrow function
$users_by_score = $users;
usort($users_by_score, fn($a, $b) => $b['score'] <=> $a['score']);

// Tri multicritères
usort($users, function($a, $b) {
    // D'abord par score (desc), puis par âge (asc)
    $score_cmp = $b['score'] <=> $a['score'];
    return $score_cmp !== 0 ? $score_cmp : $a['age'] <=> $b['age'];
});

// 4. TRI NATUREL ET AVEC VERSIONS
$versions = ['1.10', '1.2', '1.1'];
natsort($versions); // Tri naturel: ['1.1', '1.2', '1.10']

$files = ['file10.txt', 'file2.txt', 'file1.txt'];
natsort($files); // ['file1.txt', 'file2.txt', 'file10.txt']

// 5. ARRAY_MAP - Transformation
// Doubler tous les nombres
$doubles = array_map(fn($n) => $n * 2, $nombres);

// Formatter les noms
$noms_formattés = array_map(function($user) {
    return strtoupper($user['nom']);
}, $users);

// Mapper plusieurs tableaux
$noms = ['Alice', 'Bob'];
$ages = [25, 30];
$presentations = array_map(function($nom, $age) {
    return "$nom ($age ans)";
}, $noms, $ages);

// 6. ARRAY_REDUCE - Réduction
// Somme
$somme = array_reduce($nombres, fn($carry, $item) => $carry + $item, 0);

// Produit
$produit = array_reduce($nombres, fn($carry, $item) => $carry * $item, 1);

// Construire une chaîne
$phrase = array_reduce($fruits, function($carry, $fruit) {
    return $carry . ($carry ? ', ' : '') . $fruit;
}, '');

// Trouver le maximum/minimum
$max_age = array_reduce($users, function($carry, $user) {
    return max($carry, $user['age']);
}, 0);

// 7. ARRAY_WALK - Modification sur place
$prices = [10, 20, 30];
array_walk($prices, function(&$price, $key) {
    $price *= 1.2; // +20% de TVA
});

// Avec paramètre supplémentaire
array_walk($prices, function(&$price, $key, $taux) {
    $price *= (1 + $taux);
}, 0.1); // +10%

// 8. ARRAY_FLIP - Inverser clés/valeurs
$couleurs = ['r' => 'rouge', 'v' => 'vert', 'b' => 'bleu'];
$inverse = array_flip($couleurs);
// ['rouge' => 'r', 'vert' => 'v', 'bleu' => 'b']

// 9. ARRAY_REVERSE - Inverser l'ordre
$reversed = array_reverse($fruits); // ['orange', 'pomme', 'banane']
$reversed_keys = array_reverse($fruits, true); // Préserve les clés

// 10. FONCTIONS MATHÉMATIQUES
echo array_sum($nombres); // 25
echo array_product([2, 3, 4]); // 24
echo max($nombres); // 9
echo min($nombres); // 1

// Moyenne
$moyenne = array_sum($nombres) / count($nombres);
?>

Tableaux Multidimensionnels

Maîtrisez les structures de données complexes avec les tableaux à plusieurs dimensions.

📋 Structures Complexes et Parcours

<?php
// TABLEAUX MULTIDIMENSIONNELS ET STRUCTURES COMPLEXES

// 1. TABLEAUX 2D - MATRICE
$matrice = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

// Accès aux éléments
echo $matrice[1][2]; // 6 (ligne 1, colonne 2)

// Parcours avec boucles imbriquées
for ($i = 0; $i < count($matrice); $i++) {
    for ($j = 0; $j < count($matrice[$i]); $j++) {
        echo $matrice[$i][$j] . " ";
    }
    echo "\n";
}

// 2. BASE DE DONNÉES SIMULÉE
$etudiants = [
    [
        'id' => 1,
        'nom' => 'Dupont',
        'prenom' => 'Alice',
        'age' => 20,
        'notes' => [
            'maths' => 15,
            'francais' => 17,
            'anglais' => 14
        ],
        'adresse' => [
            'rue' => '123 rue de la Paix',
            'ville' => 'Paris',
            'cp' => '75001'
        ]
    ],
    [
        'id' => 2,
        'nom' => 'Martin',
        'prenom' => 'Bob',
        'age' => 22,
        'notes' => [
            'maths' => 18,
            'francais' => 12,
            'anglais' => 16
        ],
        'adresse' => [
            'rue' => '456 avenue Victor Hugo',
            'ville' => 'Lyon',
            'cp' => '69000'
        ]
    ]
];

// Accès aux données imbriquées
echo $etudiants[0]['notes']['maths']; // 15
echo $etudiants[1]['adresse']['ville']; // Lyon

// 3. PARCOURS RÉCURSIF
function parcourirRecursif($array, $niveau = 0) {
    $indentation = str_repeat("  ", $niveau);
    
    foreach ($array as $cle => $valeur) {
        if (is_array($valeur)) {
            echo $indentation . $cle . ": Array\n";
            parcourirRecursif($valeur, $niveau + 1);
        } else {
            echo $indentation . $cle . ": " . $valeur . "\n";
        }
    }
}

parcourirRecursif($etudiants[0]);

// 4. RECHERCHE DANS TABLEAUX MULTIDIMENSIONNELS
function rechercherEtudiant($etudiants, $champ, $valeur) {
    foreach ($etudiants as $index => $etudiant) {
        if (isset($etudiant[$champ]) && $etudiant[$champ] === $valeur) {
            return $index;
        }
    }
    return -1;
}

$index_alice = rechercherEtudiant($etudiants, 'prenom', 'Alice');

// Recherche avec array_search sur colonnes extraites
$prenoms = array_column($etudiants, 'prenom');
$index_bob = array_search('Bob', $prenoms);

// 5. CALCULS SUR TABLEAUX MULTIDIMENSIONNELS
function calculerMoyenne($etudiant) {
    $notes = $etudiant['notes'];
    return array_sum($notes) / count($notes);
}

function ajouterMoyennes($etudiants) {
    return array_map(function($etudiant) {
        $etudiant['moyenne'] = calculerMoyenne($etudiant);
        return $etudiant;
    }, $etudiants);
}

$etudiants_avec_moyennes = ajouterMoyennes($etudiants);

// 6. TRI DE TABLEAUX MULTIDIMENSIONNELS
// Tri par moyenne (décroissante)
usort($etudiants_avec_moyennes, function($a, $b) {
    return $b['moyenne'] <=> $a['moyenne'];
});

// Tri par nom puis prénom
usort($etudiants, function($a, $b) {
    $nom_cmp = $a['nom'] <=> $b['nom'];
    return $nom_cmp !== 0 ? $nom_cmp : $a['prenom'] <=> $b['prenom'];
});

// 7. FUSION ET MISE À JOUR PROFONDE
function fusionProfonde($array1, $array2) {
    $resultat = $array1;
    
    foreach ($array2 as $cle => $valeur) {
        if (is_array($valeur) && isset($resultat[$cle]) && is_array($resultat[$cle])) {
            $resultat[$cle] = fusionProfonde($resultat[$cle], $valeur);
        } else {
            $resultat[$cle] = $valeur;
        }
    }
    
    return $resultat;
}

// 8. CONVERSION TABLEAU ↔ OBJETS
function arrayToObject($array) {
    if (is_array($array)) {
        return (object) array_map(__FUNCTION__, $array);
    }
    return $array;
}

function objectToArray($obj) {
    if (is_object($obj)) $obj = (array) $obj;
    if (is_array($obj)) {
        $new = [];
        foreach ($obj as $key => $val) {
            $new[$key] = objectToArray($val);
        }
    } else {
        $new = $obj;
    }
    return $new;
}

// 9. APLANISSEMENT (FLATTEN)
function aplanir($array, $separateur = '.') {
    $resultat = [];
    
    foreach ($array as $cle => $valeur) {
        if (is_array($valeur)) {
            $sous_tableau = aplanir($valeur, $separateur);
            foreach ($sous_tableau as $sous_cle => $sous_valeur) {
                $resultat[$cle . $separateur . $sous_cle] = $sous_valeur;
            }
        } else {
            $resultat[$cle] = $valeur;
        }
    }
    
    return $resultat;
}

$etudiant_aplani = aplanir($etudiants[0]);
// ['id' => 1, 'nom' => 'Dupont', 'notes.maths' => 15, 'adresse.ville' => 'Paris', ...]

// 10. VALIDATION RÉCURSIVE
function validerStructure($data, $schema) {
    foreach ($schema as $cle => $type) {
        if (!isset($data[$cle])) {
            return false;
        }
        
        if (is_array($type)) {
            if (!is_array($data[$cle]) || !validerStructure($data[$cle], $type)) {
                return false;
            }
        } else {
            if (gettype($data[$cle]) !== $type) {
                return false;
            }
        }
    }
    return true;
}

$schema_etudiant = [
    'id' => 'integer',
    'nom' => 'string',
    'notes' => [
        'maths' => 'integer',
        'francais' => 'integer'
    ]
];

$valide = validerStructure($etudiants[0], $schema_etudiant);
?>

Concepts Avancés

Explorez les techniques avancées : références, objets itérables, et patterns modernes.

Références, Performances et Optimisations

<?php
// RÉFÉRENCES, PERFORMANCES ET OPTIMISATIONS

// 1. GESTION DES RÉFÉRENCES
$original = [1, 2, 3];
$copie = $original; // Copie par valeur
$reference = &$original; // Référence

// Modification sur référence
function modifierParReference(&$array) {
    $array[] = 'nouveau';
}

modifierParReference($original); // Modifie $original directement

// Parcours par référence avec foreach
$nombres = [1, 2, 3, 4, 5];
foreach ($nombres as &$nombre) {
    $nombre *= 2; // Double chaque valeur
}
unset($nombre); // Important: détruire la référence

// 2. COPY-ON-WRITE ET OPTIMISATIONS
function demonstrationCOW() {
    $big_array = range(1, 1000000);
    
    // Pas de copie réelle ici grâce au COW
    $copy1 = $big_array;
    $copy2 = $big_array;
    
    echo memory_get_usage() . " bytes\n";
    
    // Modification déclenche la copie
    $copy1[0] = 9999;
    
    echo memory_get_usage() . " bytes\n";
}

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

// Utilisation économe en mémoire
foreach (genererNombres(1000000) as $nombre) {
    if ($nombre > 10) break; // Traite seulement les 10 premiers
    echo $nombre . " ";
}

// 4. POOLING D'OBJETS POUR TABLEAUX
class ArrayPool {
    private static $pool = [];
    
    public static function get() {
        return array_pop(self::$pool) ?: [];
    }
    
    public static function release($array) {
        array_splice($array, 0); // Vider le tableau
        self::$pool[] = $array;
    }
}

// Utilisation
$temp_array = ArrayPool::get();
$temp_array[] = 'données temporaires';
ArrayPool::release($temp_array);

// 5. LAZY LOADING POUR TABLEAUX COMPLEXES
class LazyArray implements ArrayAccess, Countable {
    private $loader;
    private $cache = [];
    private $loaded = [];
    
    public function __construct($loader) {
        $this->loader = $loader;
    }
    
    public function offsetGet($offset) {
        if (!isset($this->loaded[$offset])) {
            $this->cache[$offset] = ($this->loader)($offset);
            $this->loaded[$offset] = true;
        }
        return $this->cache[$offset];
    }
    
    public function offsetExists($offset) { return true; }
    public function offsetSet($offset, $value) { $this->cache[$offset] = $value; }
    public function offsetUnset($offset) { unset($this->cache[$offset]); }
    public function count() { return count($this->cache); }
}

// 6. BENCHMARK DES OPÉRATIONS
function benchmarkArrayOperations() {
    $size = 100000;
    $data = range(1, $size);
    
    // Test array_push vs [] =
    $start = microtime(true);
    $test1 = [];
    for ($i = 0; $i < 10000; $i++) {
        $test1[] = $i;
    }
    $time1 = microtime(true) - $start;
    
    $start = microtime(true);
    $test2 = [];
    for ($i = 0; $i < 10000; $i++) {
        array_push($test2, $i);
    }
    $time2 = microtime(true) - $start;
    
    echo "[] = : " . $time1 . "s\n";
    echo "array_push: " . $time2 . "s\n";
}

// 7. SÉRIALISATION OPTIMISÉE
class OptimizedSerializer {
    public static function serialize($data) {
        // igbinary est plus rapide que serialize() natif
        return function_exists('igbinary_serialize') 
            ? igbinary_serialize($data)
            : serialize($data);
    }
    
    public static function unserialize($data) {
        return function_exists('igbinary_unserialize')
            ? igbinary_unserialize($data)
            : unserialize($data);
    }
}

// 8. ITERATEURS PERSONNALISÉS
class ChunkedArrayIterator implements Iterator {
    private $array;
    private $chunkSize;
    private $position = 0;
    
    public function __construct($array, $chunkSize = 100) {
        $this->array = $array;
        $this->chunkSize = $chunkSize;
    }
    
    public function current() {
        return array_slice(
            $this->array, 
            $this->position * $this->chunkSize, 
            $this->chunkSize
        );
    }
    
    public function key() { return $this->position; }
    public function next() { ++$this->position; }
    public function rewind() { $this->position = 0; }
    public function valid() {
        return $this->position * $this->chunkSize < count($this->array);
    }
}

// Traitement par chunks pour économiser la mémoire
$big_data = range(1, 10000);
foreach (new ChunkedArrayIterator($big_data, 500) as $chunk) {
    // Traiter 500 éléments à la fois
    echo "Chunk de " . count($chunk) . " éléments\n";
}

// 9. MEMOISATION POUR CALCULS COÛTEUX
class Memoizer {
    private static $cache = [];
    
    public static function memoize($func) {
        return function(...$args) use ($func) {
            $key = serialize($args);
            
            if (!isset(self::$cache[$key])) {
                self::$cache[$key] = $func(...$args);
            }
            
            return self::$cache[$key];
        };
    }
}

$expensiveArrayOperation = Memoizer::memoize(function($array) {
    // Simulation d'une opération coûteuse
    usleep(100000); // 0.1 seconde
    return array_sum($array);
});

// Premier appel: lent
$result1 = $expensiveArrayOperation([1, 2, 3]);
// Deuxième appel avec mêmes paramètres: instantané
$result2 = $expensiveArrayOperation([1, 2, 3]);
?>

🎯 Patterns Modernes et Techniques Avancées

<?php
// PATTERNS MODERNES ET TECHNIQUES AVANCÉES

// 1. FLUENT INTERFACE POUR TABLEAUX
class FluentArray {
    private $data;
    
    public function __construct($data = []) {
        $this->data = $data;
    }
    
    public function filter($callback) {
        $this->data = array_filter($this->data, $callback);
        return $this;
    }
    
    public function map($callback) {
        $this->data = array_map($callback, $this->data);
        return $this;
    }
    
    public function sort($callback = null) {
        $callback ? usort($this->data, $callback) : sort($this->data);
        return $this;
    }
    
    public function unique() {
        $this->data = array_values(array_unique($this->data));
        return $this;
    }
    
    public function toArray() {
        return $this->data;
    }
}

// Utilisation fluide
$result = (new FluentArray([1, 2, 2, 3, 4, 5]))
    ->unique()
    ->filter(fn($x) => $x > 2)
    ->map(fn($x) => $x * 10)
    ->sort()
    ->toArray();

// 2. PIPELINE DE TRAITEMENT
class ArrayPipeline {
    private $steps = [];
    
    public function addStep($callback) {
        $this->steps[] = $callback;
        return $this;
    }
    
    public function process($data) {
        return array_reduce($this->steps, function($carry, $step) {
            return $step($carry);
        }, $data);
    }
}

$pipeline = (new ArrayPipeline())
    ->addStep(fn($arr) => array_filter($arr, fn($x) => $x % 2 === 0))
    ->addStep(fn($arr) => array_map(fn($x) => $x * 2, $arr))
    ->addStep(fn($arr) => array_sum($arr));

$result = $pipeline->process([1, 2, 3, 4, 5, 6]); // 24

// 3. OBSERVER PATTERN POUR TABLEAUX
class ObservableArray implements ArrayAccess {
    private $data = [];
    private $observers = [];
    
    public function addObserver($observer) {
        $this->observers[] = $observer;
    }
    
    private function notify($event, $key, $value = null) {
        foreach ($this->observers as $observer) {
            $observer($event, $key, $value);
        }
    }
    
    public function offsetSet($key, $value) {
        $isNew = !isset($this->data[$key]);
        $this->data[$key] = $value;
        $this->notify($isNew ? 'added' : 'updated', $key, $value);
    }
    
    public function offsetGet($key) { return $this->data[$key] ?? null; }
    public function offsetExists($key) { return isset($this->data[$key]); }
    public function offsetUnset($key) {
        unset($this->data[$key]);
        $this->notify('removed', $key);
    }
}

// 4. COMMAND PATTERN POUR OPÉRATIONS
interface ArrayCommand {
    public function execute($array);
    public function undo($array);
}

class AddElementCommand implements ArrayCommand {
    private $value;
    private $key;
    
    public function __construct($value, $key = null) {
        $this->value = $value;
        $this->key = $key;
    }
    
    public function execute($array) {
        if ($this->key !== null) {
            $array[$this->key] = $this->value;
        } else {
            $array[] = $this->value;
        }
        return $array;
    }
    
    public function undo($array) {
        if ($this->key !== null) {
            unset($array[$this->key]);
        } else {
            array_pop($array);
        }
        return $array;
    }
}

// 5. STRATEGY PATTERN POUR TRI
interface SortStrategy {
    public function sort($array);
}

class QuickSortStrategy implements SortStrategy {
    public function sort($array) {
        if (count($array) < 2) return $array;
        
        $pivot = $array[0];
        $left = array_filter(array_slice($array, 1), fn($x) => $x <= $pivot);
        $right = array_filter(array_slice($array, 1), fn($x) => $x > $pivot);
        
        return array_merge($this->sort($left), [$pivot], $this->sort($right));
    }
}

class ArraySorter {
    private $strategy;
    
    public function __construct(SortStrategy $strategy) {
        $this->strategy = $strategy;
    }
    
    public function sort($array) {
        return $this->strategy->sort($array);
    }
}

// 6. DECORATOR PATTERN
class ArrayDecorator {
    protected $array;
    
    public function __construct($array) {
        $this->array = $array;
    }
    
    public function getData() { return $this->array; }
}

class ValidatedArrayDecorator extends ArrayDecorator {
    private $validator;
    
    public function __construct($array, $validator) {
        parent::__construct($array);
        $this->validator = $validator;
    }
    
    public function getData() {
        return array_filter($this->array, $this->validator);
    }
}

// 7. IMMUTABLE ARRAYS
class ImmutableArray {
    private $data;
    
    public function __construct($data) {
        $this->data = $data;
    }
    
    public function add($value) {
        $newData = $this->data;
        $newData[] = $value;
        return new self($newData);
    }
    
    public function filter($callback) {
        return new self(array_filter($this->data, $callback));
    }
    
    public function toArray() { return $this->data; }
}

// 8. WEAK REFERENCES POUR CACHES
class WeakArrayCache {
    private $cache;
    
    public function __construct() {
        $this->cache = new WeakMap();
    }
    
    public function get($object) {
        return $this->cache[$object] ?? null;
    }
    
    public function set($object, $data) {
        $this->cache[$object] = $data;
    }
}
?>

Exemples Pratiques

Découvrez des cas d'usage concrets avec CodeIgniter 4 et des applications web modernes.

🌐 Applications Web et CodeIgniter 4

<?php
// EXEMPLES PRATIQUES AVEC CODEIGNITER 4

// 1. CONTROLLER AVEC GESTION DE TABLEAUX
class ProductController extends BaseController {
    
    public function index() {
        $model = new ProductModel();
        $products = $model->findAll();
        
        // Traitement avec tableaux
        $data = [
            'products' => $this->processProducts($products),
            'categories' => $this->getCategories($products),
            'stats' => $this->calculateStats($products)
        ];
        
        return view('products/index', $data);
    }
    
    private function processProducts($products) {
        // Grouper par catégorie
        $grouped = [];
        foreach ($products as $product) {
            $category = $product['category'];
            $grouped[$category][] = $product;
        }
        
        // Trier chaque groupe par prix
        foreach ($grouped as &$group) {
            usort($group, fn($a, $b) => $a['price'] <=> $b['price']);
        }
        
        return $grouped;
    }
    
    private function getCategories($products) {
        $categories = array_column($products, 'category');
        $unique = array_unique($categories);
        sort($unique);
        return $unique;
    }
    
    private function calculateStats($products) {
        $prices = array_column($products, 'price');
        
        return [
            'total' => count($products),
            'avg_price' => array_sum($prices) / count($prices),
            'min_price' => min($prices),
            'max_price' => max($prices)
        ];
    }
}

// 2. HELPER POUR TABLEAUX
if (!function_exists('array_pluck')) {
    function array_pluck($array, $key) {
        return array_map(fn($item) => $item[$key] ?? null, $array);
    }
}

if (!function_exists('array_group_by')) {
    function array_group_by($array, $key) {
        $result = [];
        foreach ($array as $item) {
            $groupKey = $item[$key] ?? 'unknown';
            $result[$groupKey][] = $item;
        }
        return $result;
    }
}

// 3. VALIDATION DE FORMULAIRES
class FormController extends BaseController {
    
    public function create() {
        $validation = service('validation');
        
        // Règles de validation sous forme de tableau
        $rules = [
            'name' => 'required|min_length[3]|max_length[50]',
            'email' => 'required|valid_email|is_unique[users.email]',
            'skills' => 'required',
            'experience' => 'required|integer|greater_than[0]'
        ];
        
        if (!$this->validate($rules)) {
            return view('form', [
                'errors' => $validation->getErrors()
            ]);
        }
        
        // Nettoyage et transformation des données
        $data = $this->sanitizeData($this->request->getPost());
        
        // Sauvegarde...
    }
    
    private function sanitizeData($input) {
        $clean = [];
        
        // Nettoyer chaque champ
        $cleaners = [
            'name' => fn($val) => trim(strip_tags($val)),
            'email' => fn($val) => filter_var($val, FILTER_SANITIZE_EMAIL),
            'skills' => fn($val) => array_map('trim', explode(',', $val)),
            'experience' => fn($val) => (int) $val
        ];
        
        foreach ($cleaners as $field => $cleaner) {
            if (isset($input[$field])) {
                $clean[$field] = $cleaner($input[$field]);
            }
        }
        
        return $clean;
    }
}

// 4. CACHE ET SESSION
class CacheService {
    
    public function cacheArray($key, $data, $ttl = 3600) {
        $cache = service('cache');
        
        // Compression pour économiser l'espace
        $compressed = gzcompress(serialize($data));
        
        return $cache->save($key, $compressed, $ttl);
    }
    
    public function getCachedArray($key) {
        $cache = service('cache');
        $compressed = $cache->get($key);
        
        if ($compressed === null) {
            return null;
        }
        
        return unserialize(gzuncompress($compressed));
    }
}

// 5. API AVEC PAGINATION
class ApiController extends BaseController {
    
    public function getUsers() {
        $page = $this->request->getGet('page') ?? 1;
        $limit = $this->request->getGet('limit') ?? 10;
        $filters = $this->getFilters();
        
        $model = new UserModel();
        $users = $model->getFilteredUsers($filters, $page, $limit);
        
        $response = [
            'data' => $users,
            'pagination' => [
                'current_page' => $page,
                'per_page' => $limit,
                'total' => $model->countFiltered($filters)
            ],
            'filters_applied' => $filters
        ];
        
        return $this->response->setJSON($response);
    }
    
    private function getFilters() {
        $allowed = ['name', 'email', 'status', 'role'];
        $filters = [];
        
        foreach ($allowed as $field) {
            $value = $this->request->getGet($field);
            if ($value !== null) {
                $filters[$field] = trim($value);
            }
        }
        
        return $filters;
    }
}

// 6. CONFIGURATION DYNAMIQUE
class ConfigHelper {
    
    public static function mergeConfigs($base, $override) {
        foreach ($override as $key => $value) {
            if (is_array($value) && isset($base[$key]) && is_array($base[$key])) {
                $base[$key] = self::mergeConfigs($base[$key], $value);
            } else {
                $base[$key] = $value;
            }
        }
        return $base;
    }
    
    public static function getNestedValue($array, $path, $default = null) {
        $keys = explode('.', $path);
        $current = $array;
        
        foreach ($keys as $key) {
            if (!is_array($current) || !isset($current[$key])) {
                return $default;
            }
            $current = $current[$key];
        }
        
        return $current;
    }
}
?>