Manipulation de fichiers

Présentation

Manipuler des fichiers en PHP revient souvent à faire deux types d'actions. Certaines actions concernent le chemin, par exemple vérifier qu'un fichier existe, lister un dossier, renommer un élément, ou supprimer un élément.

D'autres actions concernent le contenu d'un fichier. Dans ce chapitre, l'objectif est de rester sur une approche simple et directe. Elle convient bien pour des fichiers petits ou moyens, avec des opérations classiques.

Pour éviter les surprises liées aux chemins relatifs, les exemples utilisent __DIR__ afin de construire des chemins stables.

Si vous devez lire ou écrire progressivement, traiter un gros fichier, ou contrôler finement les étapes de lecture et d'écriture, un chapitre basé sur la manipulation par pointeur sera plus adapté.

Vérifier l'existence d'un fichier ou d'un dossier

La fonction file_exists() vérifie si un élément existe à l'emplacement indiqué. Elle peut viser un fichier ou un dossier.


                    <?php
                    // Construire un chemin stable grâce à __DIR__.
                    // Ainsi, le chemin ne dépend pas du dossier depuis lequel le script est appelé.
                    $chemin = __DIR__ . '/mon_fichier.txt';

                    // file_exists() indique uniquement si l'élément existe.
                    // Il ne confirme pas s'il s'agit d'un fichier ou d'un dossier.
                    if (file_exists($chemin))
                    {
                        echo 'L\'élément existe.';
                    }
                    else
                    {
                        echo 'L\'élément n\'existe pas.';
                    }
                

Cette fonction indique uniquement si l'élément existe. Elle ne confirme pas si le script a le droit de le lire ou de le modifier.

Vérifier si un fichier est accessible en lecture

La fonction is_readable() confirme qu'un élément existe et qu'il est accessible en lecture au moment de l'exécution.


                    <?php
                    // Ici, on vérifie une situation plus précise que file_exists().
                    // On veut confirmer que la lecture sera possible avant d'essayer de lire le contenu.
                    $cheminFichier = __DIR__ . '/mon_fichier.txt';

                    if (is_readable($cheminFichier))
                    {
                        echo 'Le fichier existe et peut être lu.';
                    }
                    else
                    {
                        echo 'Lecture impossible. Fichier absent ou droits insuffisants.';
                    }
                

Vérifier si l'élément est un dossier

La fonction is_dir() confirme que le chemin vise un dossier. Si le chemin n'existe pas ou vise un fichier, le résultat est false.


                    <?php
                    // is_dir() est un test direct.
                    // Le résultat est true uniquement si le chemin existe et vise bien un dossier.
                    $cheminDossier = __DIR__ . '/monDossier';

                    if (is_dir($cheminDossier))
                    {
                        echo 'C\'est bien un dossier.';
                    }
                    else
                    {
                        echo 'Ce n\'est pas un dossier.';
                    }
                

Lister le contenu d'un dossier

Pour obtenir la liste des éléments présents dans un dossier, utilisez scandir().

Structure de fichiers


                    📁 projet/
                    ├── 📄 index.php
                    └── 📁 monDossier/
                        ├── 📁 unAutreDossier/
                        ├── 📄 fichier1.php
                        ├── 📄 fichier2.php
                        └── 📄 fichier3.php
                

                    <?php
                    $cheminDossier = __DIR__ . '/monDossier';

                    // Éviter d'appeler scandir() si le dossier n'existe pas.
                    // Cela permet de garder un comportement clair, avec un message explicite.
                    if (!is_dir($cheminDossier))
                    {
                        echo 'Le dossier n\'existe pas.';
                    }
                    else
                    {
                        // scandir() renvoie un tableau de noms (fichiers et dossiers).
                        // Les noms sont renvoyés tels quels, sans indiquer leur type.
                        $liste = scandir($cheminDossier);

                        print_r($liste);
                        /*
                            Affiche :
                                Array
                                (
                                    [0] => .
                                    [1] => ..
                                    [2] => fichier1.php
                                    [3] => fichier2.php
                                    [4] => fichier3.php
                                    [5] => unAutreDossier
                                )
                        */
                    }
                

scandir() renvoie aussi . et ... Pour ignorer ces deux éléments, vous pouvez filtrer la liste.


                    <?php
                    $cheminDossier = __DIR__ . '/monDossier';

                    $liste = scandir($cheminDossier);

                    /*
                        array_diff() retire d'un tableau toutes les valeurs présentes dans un autre tableau.

                        Ici, scandir() renvoie toujours "." et "..".
                        - "."  signifie "le dossier courant"
                        - ".." signifie "le dossier parent"

                        On ne veut pas les garder dans notre liste, donc on les retire.
                    */
                    $liste = array_diff($liste, ['.', '..']);

                    print_r($liste);
                    /*
                        Attention.

                        array_diff() retire des valeurs, mais il ne réorganise pas les index.
                        Les index 0 et 1 ont disparu, donc la liste commence à 2.

                        Exemple :
                            Array
                            (
                                [2] => fichier1.php
                                [3] => fichier2.php
                                [4] => fichier3.php
                                [5] => unAutreDossier
                            )
                    */

                    /*
                        array_values() sert à réindexer un tableau numéroté à partir de 0.

                        On l'utilise ici pour retrouver une liste "propre" avec des index 0, 1, 2, 3...
                    */
                    $liste = array_values($liste);

                    print_r($liste);
                    /*
                        Array
                        (
                            [0] => fichier1.php
                            [1] => fichier2.php
                            [2] => fichier3.php
                            [3] => unAutreDossier
                        )
                    */
                

Créer un dossier

Pour créer un dossier en PHP, utilisez la fonction mkdir(). Elle reçoit le chemin du dossier à créer.

mkdir() renvoie true si la création a réussi, sinon false.


                    <?php
                    $cheminDossier = __DIR__ . '/nouveauDossier';

                    if (mkdir($cheminDossier))
                    {
                        echo 'Dossier créé.';
                    }
                    else
                    {
                        echo 'Création du dossier impossible.';
                    }
                

Par défaut, mkdir() ne crée qu'un seul niveau de dossier. Si le dossier parent n'existe pas, la création échoue.

mkdir() accepte des arguments optionnels :

  • Le second argument correspond au mode de permissions demandé lors de la création du dossier. La valeur 0777 signifie que le dossier est lisible, modifiable et exécutable par tous les utilisateurs. Le système peut toutefois restreindre ces permissions selon sa configuration.
  • Le troisième argument est un booléen. S'il vaut true, PHP peut créer tous les dossiers manquants dans le chemin. Sans cela, seul le dernier dossier est créé.

                    <?php
                    $cheminDossier = __DIR__ . '/archives/2026/janvier';

                    // 0777 demande des permissions larges.
                    // true active la création récursive (création des dossiers parents si nécessaire).
                    if (mkdir($cheminDossier, 0777, true))
                    {
                        echo 'Arborescence créée.';
                    }
                    else
                    {
                        echo 'Création impossible.';
                    }
                

Avant de créer un dossier, il est recommandé de vérifier s'il n'existe pas déjà, afin d'éviter une erreur inutile.


                    <?php
                    $cheminDossier = __DIR__ . '/archives';

                    if (!is_dir($cheminDossier))
                    {
                        mkdir($cheminDossier);
                    }
                

Comme pour les autres opérations sur les fichiers, l'utilisation de __DIR__ permet de construire des chemins stables, indépendants du dossier depuis lequel le script est exécuté.

Supprimer un dossier

Pour supprimer un dossier, utilisez rmdir(). Cette fonction ne peut supprimer qu'un dossier vide.


                    <?php
                    $cheminDossier = __DIR__ . '/monDossier';

                    // On vérifie directement qu'il s'agit bien d'un dossier existant.
                    if (!is_dir($cheminDossier))
                    {
                        echo 'Le dossier n\'existe pas.';
                    }
                    else
                    {
                        // rmdir() renvoie false si le dossier n'est pas vide ou si les droits sont insuffisants.
                        $suppressionOk = rmdir($cheminDossier);

                        if ($suppressionOk)
                        {
                            echo 'Dossier supprimé.';
                        }
                        else
                        {
                            echo 'Impossible de supprimer le dossier. Il n\'est peut-être pas vide.';
                        }
                    }
                

Pour supprimer un dossier non vide, il faut d'abord supprimer son contenu, puis supprimer le dossier. Cette logique demande une fonction dédiée et sort du cadre de ce chapitre.

Copier un fichier

La fonction copy() permet de copier un fichier vers un nouvel emplacement. Elle reçoit deux chemins. Le premier correspond au fichier source, le second correspond au fichier de destination.

copy() retourne true si la copie a réussi, sinon false. Le fichier source reste intact.


                    <?php
                    $cheminSource = __DIR__ . '/mon_fichier.txt';
                    $cheminDestination = __DIR__ . '/archives/mon_fichier.txt';

                    // Vérifier que le fichier source existe.
                    if (!file_exists($cheminSource))
                    {
                        echo 'Le fichier source n\'existe pas.';
                    }
                    else
                    {
                        // Copier le fichier.
                        if (copy($cheminSource, $cheminDestination))
                        {
                            echo 'Copie effectuée.';
                        }
                        else
                        {
                            echo 'Copie impossible. Chemin invalide ou droits insuffisants.';
                        }
                    }
                

La copie est utile lorsqu'on souhaite conserver une version originale, par exemple pour créer une sauvegarde avant une modification.

Elle est aussi utilisée comme étape intermédiaire pour déplacer un fichier lorsque rename() ne peut pas fonctionner, notamment si la destination se trouve sur un autre disque ou une autre partition. Dans ce cas, le déplacement se fait en deux actions. D'abord copier, ensuite supprimer l'original avec unlink().

Supprimer un fichier

La fonction unlink() supprime un fichier. Elle renvoie true si la suppression a réussi, sinon false.

Avant de supprimer, vérifier l'existence évite des échecs inutiles. Il faut aussi éviter de viser un dossier, car unlink() ne supprime pas les dossiers.


                    <?php
                    $chemin = __DIR__ . '/mon_fichier.txt';

                    // Vérifier l'existence évite un appel inutile à unlink().
                    if (!file_exists($chemin))
                    {
                        echo 'Le fichier n\'existe pas.';
                    }
                    // unlink() ne supprime pas les dossiers.
                    // Ce test évite une confusion fréquente entre fichier et dossier.
                    else if (is_dir($chemin))
                    {
                        echo 'Le chemin vise un dossier. Utiliser une suppression de dossier.';
                    }
                    else
                    {
                        $suppressionOk = unlink($chemin);

                        if ($suppressionOk)
                        {
                            echo 'Fichier supprimé.';
                        }
                        else
                        {
                            echo 'Suppression impossible. Droits insuffisants ou fichier verrouillé.';
                        }
                    }
                

Renommer un fichier ou un dossier

La fonction rename() permet de renommer un fichier ou un dossier. Elle reçoit deux chemins. Le premier correspond au chemin actuel de l'élément, le second correspond à son nouveau nom.


                    <?php
                    $ancienNom = __DIR__ . '/mon_fichier.txt';
                    $nouveauNom = __DIR__ . '/archive.txt';

                    // Vérifier que l'élément source existe.
                    if (!file_exists($ancienNom))
                    {
                        echo 'L\'élément à renommer n\'existe pas.';
                    }
                    else
                    {
                        // rename() retourne true en cas de succès, false en cas d'échec.
                        if (rename($ancienNom, $nouveauNom))
                        {
                            echo 'Renommage effectué.';
                        }
                        else
                        {
                            echo 'Renommage impossible. Chemin invalide ou droits insuffisants.';
                        }
                    }
                

Dans ce cas, seul le nom change. Le fichier reste dans le même dossier et sur le même support de stockage.

Déplacer un fichier ou un dossier

La fonction rename() peut aussi être utilisée pour déplacer un fichier ou un dossier. Pour cela, il suffit que le second chemin pointe vers un autre dossier.


                    <?php
                    $ancienNom = __DIR__ . '/mon_fichier.txt';
                    $nouveauNom = __DIR__ . '/archives/mon_fichier.txt';

                    // Le nom reste identique, mais le dossier change.
                    // Le résultat correspond à un déplacement.
                    rename($ancienNom, $nouveauNom);
                

Cette approche fonctionne tant que le fichier source et le dossier de destination se trouvent sur le même système de fichiers, c'est-à-dire sur le même disque ou la même partition.

Si vous tentez de déplacer un fichier vers un autre disque, un disque externe ou un volume différent, rename() peut échouer et retourner false.

Dans ce contexte, il faut adopter une autre stratégie. Le déplacement se fait alors en deux étapes : copier le fichier, puis supprimer l'original.


                    <?php
                    $source = __DIR__ . '/mon_fichier.txt';
                    $destination = '/autre-disque/archives/mon_fichier.txt';

                    // Vérifier que le fichier source existe.
                    if (!file_exists($source))
                    {
                        echo 'Le fichier source n\'existe pas.';
                    }
                    else
                    {
                        // Attention.
                        // Cette version ne fonctionne que pour un fichier.
                        // copy() et unlink() ne s'appliquent pas aux dossiers.
                        if (copy($source, $destination))
                        {
                            // Supprimer le fichier original uniquement si la copie a réussi.
                            unlink($source);
                            echo 'Déplacement effectué par copie.';
                        }
                        else
                        {
                            echo 'Copie impossible. Vérifiez les chemins ou les droits.';
                        }
                    }
                

Attention, la stratégie copy() puis unlink() fonctionne uniquement pour un fichier. Un dossier ne peut pas être copié avec copy() et ne peut pas être supprimé avec unlink().

Si vous souhaitez déplacer un dossier entre deux supports distincts, il faut passer par la récursivité. Cela consiste à écrire une fonction qui s'appelle elle-même pour parcourir toute l'arborescence.

Le principe général repose sur une copie récursive du dossier, suivie d'une suppression récursive.

Principe de la copie récursive :

  1. Lire la liste des éléments contenus dans le dossier courant.
  2. Pour chaque élément rencontré, déterminer s'il s'agit d'un fichier ou d'un dossier.
  3. Si l'élément est un fichier, le copier vers le dossier de destination.
  4. Si l'élément est un dossier, créer le dossier correspondant dans la destination, puis rappeler la même fonction avec le chemin mis à jour afin de traiter le contenu de ce sous-dossier.

Une fois la copie terminée, le même principe est appliqué pour la suppression :

  1. Parcourir à nouveau le dossier source.
  2. Supprimer chaque fichier rencontré.
  3. Pour chaque sous-dossier, rappeler la fonction de suppression afin de vider son contenu.
  4. Lorsque le dossier est vide, le supprimer avec rmdir().

Cette méthode est utilisée lorsque rename() ne peut pas fonctionner, notamment lors d'un déplacement entre deux supports distincts. Elle est plus coûteuse, mais garantit un comportement fiable dans tous les contextes.

Lire un fichier complet

Une solution simple pour lire un fichier consiste à utiliser file_get_contents(). PHP lit tout le fichier et renvoie son contenu sous forme de chaîne de caractères.

Le contenu est chargé en mémoire et placé dans une variable. Vous travaillez donc sur une copie du contenu.

Si la lecture échoue, la fonction renvoie false. Cela peut arriver si le fichier n'existe pas ou si le script n'a pas les droits nécessaires.


                    <?php
                    $cheminFichier = __DIR__ . '/mon_fichier.txt';

                    // Si la lecture échoue, file_get_contents() renvoie false.
                    // Cela évite d'utiliser une variable de contenu invalide.
                    $contenuFichier = file_get_contents($cheminFichier);

                    if ($contenuFichier === false)
                    {
                        echo 'Impossible de lire le fichier.';
                    }
                    else
                    {
                        // On modifie la copie en mémoire.
                        // Le fichier sur le disque ne change pas tant qu'on ne l'enregistre pas explicitement.
                        $contenuFichier .= 'Ma nouvelle ligne' . PHP_EOL;

                        echo $contenuFichier;
                    }
                

Écrire un fichier complet

Pour enregistrer du texte dans un fichier, utilisez file_put_contents(). Par défaut, cette fonction remplace le contenu existant. Si le fichier n'existe pas, il est créé.

Si l'écriture échoue, la fonction renvoie false. Sinon, elle renvoie généralement le nombre d'octets écrits.


                    <?php
                    $cheminFichier = __DIR__ . '/mon_fichier.txt';

                    // Construire le contenu en mémoire avant de l'enregistrer dans le fichier.
                    $contenu = "Première ligne" . PHP_EOL;
                    $contenu .= "Deuxième ligne" . PHP_EOL;

                    $resultat = file_put_contents($cheminFichier, $contenu);

                    // file_put_contents() renvoie false si l'écriture échoue.
                    if ($resultat === false)
                    {
                        echo 'Impossible d\'écrire dans le fichier.';
                    }
                

Pour ajouter du contenu à la fin du fichier au lieu de remplacer, utilisez le flag FILE_APPEND.


                    <?php
                    $cheminFichier = __DIR__ . '/mon_fichier.txt';

                    // FILE_APPEND indique que l'on veut ajouter à la fin du fichier.
                    file_put_contents($cheminFichier, 'Nouvelle ligne' . PHP_EOL, FILE_APPEND);
                

Pour réduire les écritures concurrentes pendant l'appel, combinez avec LOCK_EX. Le verrou est appliqué uniquement pendant cet appel.


                    <?php
                    $cheminFichier = __DIR__ . '/mon_fichier.txt';

                    // LOCK_EX applique un verrou exclusif pendant cet appel.
                    // Cela réduit le risque que deux scripts écrivent au même moment.
                    file_put_contents($cheminFichier, 'Nouvelle ligne' . PHP_EOL, FILE_APPEND | LOCK_EX);
                

Les fichiers JSON

Un fichier JSON stocke des données structurées sous forme de texte. En PHP, le principe est simple. Lire le fichier, décoder le JSON en tableau, manipuler les données, puis réencoder et sauvegarder.

Contenu du fichier JSON "exemple.json"


                    {
                        "nourriture": [
                            "pomme",
                            "pain",
                            "fromage"
                        ],
                        "animaux": [
                            "chien",
                            "chat",
                            "oiseau"
                        ],
                        "professions": [
                            "médecin",
                            "enseignant",
                            "policier"
                        ]
                    }
                

Importer un JSON et le convertir en tableau


                    <?php
                    $cheminFichierJSON = __DIR__ . '/exemple.json';

                    $contenuJSON = file_get_contents($cheminFichierJSON);

                    // Si la lecture échoue, on évite d'essayer de décoder une valeur invalide.
                    if ($contenuJSON === false)
                    {
                        echo 'Impossible de lire le fichier JSON.';
                    }
                    else
                    {
                        // Le second argument à true demande un tableau associatif plutôt qu'un objet.
                        $data = json_decode($contenuJSON, true);

                        // Si le JSON est invalide, json_decode() renvoie null.
                        if ($data === null)
                        {
                            echo 'Le contenu n\'est pas un JSON valide.';
                        }
                        else
                        {
                            print_r($data);
                        }
                    }
                

Une fois les données sous forme de tableau, vous pouvez les modifier comme n'importe quel tableau associatif. Ensuite, il faut réencoder en JSON et sauvegarder dans le fichier.

Modifier des données, réencoder en JSON et enregistrer


                    <?php
                    $data['animaux'][1] = 'canard';

                    // JSON_PRETTY_PRINT rend le JSON plus lisible dans le fichier.
                    $exempleModifie = json_encode($data, JSON_PRETTY_PRINT);

                    file_put_contents(__DIR__ . '/exemple.json', $exempleModifie);
                

Si vous désirez obtenir plus d'informations, consultez la documentation officielle du système de fichiers. Système de fichiers

Exercices

PHP: Tirage sans doublon en ligne de commande - Exo 01

Cet exercice consiste à construire une mini application en ligne de commande. Elle permet d'importer une liste depuis un fichier JSON, de tirer des valeurs aléatoires sans doublon, d'afficher l'historique et de réinitialiser un cycle.

Le projet est volontairement séparé en deux zones. Le dossier src contient des fonctions réutilisables. Le dossier bin contient des scripts exécutables depuis le terminal.

Attendu

Vous devez être capable de réaliser les actions suivantes. Importer une liste depuis un fichier JSON externe. Tirer une valeur au hasard sans doublon, jusqu'à épuisement de la liste. Afficher un historique numéroté des tirages. Réinitialiser un cycle afin de repartir de zéro.

Le stockage doit être persistant sur le disque dans un dossier data. Une liste est identifiée par un identifiant idListe. Pour chaque identifiant, on stocke trois fichiers.

liste.json contient la liste officielle, stable. restants.json contient la liste de travail du cycle en cours. historique.json contient l'historique des tirages.

Structure

Créer un dossier nommé Exo-01-php-cli-tirage-sans-doublon, puis organiser les fichiers en respectant l'arborescence suivante.


                    📁 Exo-01-php-cli-tirage-sans-doublon/
                    ├── 📁 src/
                    │   ├── 📄 chemins.php
                    │   ├── 📄 creerDossier.php
                    │   ├── 📄 json.php
                    │   ├── 📄 listes.php
                    │   ├── 📄 historique.php
                    │   └── 📄 tirage.php
                    ├── 📁 bin/
                    │   ├── 📄 importer.php
                    │   ├── 📄 tirer.php
                    │   ├── 📄 historique.php
                    │   └── 📄 reinitialiser.php
                    ├── 📁 imports/
                    │   └── 📄 exemple-liste.json
                    └── 📁 data/
                        └── (créé automatiquement par le code)
                

Fichier fourni

Copier le fichier suivant à l'identique. Il s'agit d'un exemple de liste externe qui sera importée dans le stockage du projet.

/imports/exemple-liste.json


                    [
                        "Alice",
                        "Bob",
                        "Chloé",
                        "David",
                        "Emma"
                    ]
                

Instructions

Vous allez d'abord construire tout le dossier src. Pour tester vos fonctions au fur et à mesure, vous allez créer un fichier index.php temporaire à la racine.

Ce fichier index.php n'existera pas dans la version finale. Il sert uniquement à tester les fichiers du dossier src avant de passer aux scripts du dossier bin.

Étape 01

Mettre en place le terrain de travail. Créer l'arborescence du projet et préparer un point d'entrée temporaire pour les tests.

  1. Créer tous les dossiers et fichiers de la structure. À ce stade, les fichiers peuvent être vides.
  2. À la racine du projet, créer un fichier nommé index.php. Ce fichier servira uniquement aux tests de src.
  3. Dans index.php, activer le typage strict (declare(strict_types=1)).
    • Le fichier index.php sert de script de test. Vous allez y appeler beaucoup de fonctions, en leur passant des paramètres (idListe, chemins de fichiers, tableaux, etc.).
    • Activer le typage strict permet d'être plus exigeant sur les types passés aux fonctions. Ainsi, si vous appelez une fonction en lui donnant un mauvais type (ex.: un nombre au lieu d'une chaîne), PHP ne tente pas de "deviner" ou de convertir automatiquement. Le but est de repérer les erreurs plus tôt, au moment où vous testez.

Étape 02

Dans cette étape, vous allez construire une série de fonctions qui retournent des chemins. L'idée est de centraliser tous les chemins du projet dans un seul fichier. Ainsi, le reste du code n'a plus besoin de réécrire /data, /data/listes ou les chemins des fichiers JSON à plusieurs endroits. Ces fonctions ne créent rien sur le disque. Elles servent uniquement à fabriquer des chemins fiables à partir d'un point de départ stable.

  1. Dans index.php, inclure le fichier src/chemins.php avec require_once.
  2. Dans src/chemins.php, activer le typage strict.
  3. Dans src/chemins.php, créer la fonction getRacineProjet. Elle doit retourner un chemin absolu qui correspond à la racine du projet.
    • Pour obtenir la racine, combiner dirname et __DIR__
      • La fonction dirname permet de remonter d'un niveau du chemin qui lui est passé en premier argument.
      • La constante magique __DIR__ correspond au dossier dans lequel elle est utilisée (ici, src).
  4. Tester la fonction getRacineProjet. Dans index.php, appeler la fonction puis afficher le résultat avec echo. Vous devez obtenir le chemin absolu du dossier du projet, celui qui contient src, bin et imports. Relancer php ./index.php pour vérifier.
  5. Dans src/chemins.php, créer la fonction getDossierData pour obtenir le chemin du dossier data du projet. Ce dossier servira à stocker les données du programme sur le disque, comme les fichiers JSON des listes. La fonction ne crée rien, elle retourne simplement getRacineProjet() suivi de /data.
  6. Tester la fonction getDossierData. Dans index.php, appeler la fonction puis afficher le résultat avec echo. Le chemin affiché doit se terminer par /data.
  7. Dans src/chemins.php, créer la fonction getDossierListes pour obtenir le chemin du dossier data/listes. Ce dossier regroupera toutes les listes importées. Chaque liste sera ensuite rangée dans un sous-dossier séparé. La fonction ne crée rien, elle retourne simplement getDossierData() suivi de /listes.
  8. Tester la fonction getDossierListes. Dans index.php, appeler la fonction puis afficher le résultat avec echo. Le chemin affiché doit se terminer par /data/listes.
  9. Dans src/chemins.php, créer la fonction getDossierListe pour obtenir le chemin du dossier d'une liste précise à partir de son identifiant. Ce sous-dossier représentera une liste importée, et contiendra ses fichiers liste.json, restants.json et historique.json. La fonction reçoit un paramètre $idListe et retourne getDossierListes() suivi de / puis de la valeur de $idListe.
  10. Tester la fonction getDossierListe. Dans index.php, appeler la fonction en utilisant un identifiant simple, par exemple 'test123', puis afficher le résultat avec echo. Le chemin affiché doit se terminer par /data/listes/test123.
  11. Dans src/chemins.php, créer la fonction getCheminListeJson pour obtenir le chemin du fichier officiel liste.json. Ce fichier contiendra la liste stable importée, celle qui sert de référence pour repartir sur un nouveau cycle. La fonction reçoit un paramètre $idListe et retourne getDossierListe($idListe) suivi de /liste.json.
  12. Tester la fonction getCheminListeJson. Dans index.php, appeler la fonction avec le même identifiant 'test123', puis afficher le résultat avec echo. Le chemin affiché doit se terminer par /data/listes/test123/liste.json.
  13. Dans src/chemins.php, créer la fonction getCheminRestantsJson pour obtenir le chemin du fichier de travail restants.json. Ce fichier contiendra la liste du cycle en cours, dans laquelle les éléments tirés seront retirés pour éviter les doublons. La fonction reçoit un paramètre $idListe et retourne getDossierListe($idListe) suivi de /restants.json.
  14. Tester la fonction getCheminRestantsJson. Dans index.php, appeler la fonction avec 'test123' puis afficher le résultat avec echo. Le chemin affiché doit se terminer par /data/listes/test123/restants.json.
  15. Dans src/chemins.php, créer la fonction getCheminHistoriqueJson pour obtenir le chemin du fichier historique.json. Ce fichier gardera la trace des valeurs tirées, dans l'ordre des tirages. La fonction reçoit un paramètre $idListe et retourne getDossierListe($idListe) suivi de /historique.json.
  16. Tester la fonction getCheminHistoriqueJson. Dans index.php, appeler la fonction avec 'test123' puis afficher le résultat avec echo. Le chemin affiché doit se terminer par /data/listes/test123/historique.json.
  17. Tester l'exécution depuis deux endroits.
    • Se placer à la racine et exécuter php ./index.php.
    • Se placer dans src et exécuter php ../index.php.
    Dans les deux cas, vous devez obtenir exactement les mêmes chemins.

Étape 03

Créer une fonction simple pour créer un dossier sur le disque. Cette fonction doit être réutilisable, et doit fonctionner même si le dossier existe déjà.

  1. Dans src/creerDossier.php, créer une fonction creerDossier qui contient un paramètre $cheminDossier destiné à recevoir le chemin du dossier à créer sous forme de chaîne de caractère. La fonction retourne true si le dossier existe déjà ou s'il a été créé et false si la création du dossier est impossible.
  2. Dans cette fonction, vérifier que le dossier n'existe pas encore. Pour cela, utiliser is_dir avec $cheminDossier.
    • Si is_dir retourne false, cela signifie que le dossier n'existe pas et qu'il faut tenter de le créer.
  3. Si le dossier doit être créer, utiliser mkdir avec trois arguments.
    • Premier argument, le chemin à créer $cheminDossier.
    • Deuxième argument, le mode de permission demandé 0777. Ce mode signifie "lecture, écriture et exécution pour tous".
    • Troisième argument, activer la création récursive avec true. Ainsi, si des dossiers parents manquent, PHP peut les créer automatiquement.
  4. Vérifier si la création du dossier a échoué. Pour cela, utiliser une condition qui teste le retour de mkdir. Si mkdir retourne false, retourner immédiatement false. L'échec peut venir d'un chemin invalide ou de droits insuffisants.
  5. À la suite des structures conditionnelles, tout à la fin de la fonction, ajouter un return true.
    • Ce true couvre les deux cas. Le dossier existait déjà, on n'a rien eu à faire. Le dossier n'existait pas, on l'a créé avec succès.
  6. Tester la fonction via index.php.
    • Dans index.php, inclure src/chemins.php et src/creerDossier.php.
    • Construire un chemin vers un dossier de test à la racine du projet. Utiliser getRacineProjet() puis ajouter /test. Ce dossier test sera créé automatiquement lors de l'exécution.
    • Appeler creerDossier avec ce chemin et stocker la valeur retournée dans une variable, par exemple $ok.
    • Selon la valeur retournée, afficher un message dans le terminal.
      • Si la variable vaut true, afficher "OK. Dossier de test prêt.".
      • Si la variable vaut false, afficher "Erreur. Impossible de créer le dossier de test.".
    • Exécuter index.php depuis la racine du projet avec php ./index.php. Vérifier deux choses.
      • Le dossier test apparaît bien à la racine du projet.
      • Le message affiché est bien un message de succès.
    • Relancer le script une deuxième fois. Le dossier existe déjà. Le script doit rester en succès, car la fonction doit retourner true même si elle n'a rien eu à créer.

Étape 04

Lire et écrire des tableaux dans des fichiers JSON. Votre code doit rester stable même si le fichier est vide, absent ou invalide.

  1. Dans src/json.php, activer le typage strict.
  2. Dans src/json.php, créer une fonction nommée lireJsonTableau. Elle permettra de récupérer un tableau PHP à partir d'un fichier JSON stocké sur le disque. Cette fonction sera utilisée dans tout le projet pour charger les listes, les restants et l'historique.
    • La fonction reçoit un paramètre $cheminFichier de type string. Il représente le chemin du fichier JSON à lire (ex.:data/listes/abc123/liste.json).
    • La fonction doit retourner un tableau de type array. Ce tableau représentera le contenu du JSON sous une forme directement utilisable en PHP.
  3. Dans lireJsonTableau, commencer par gérer le cas où le fichier n'existe pas.
    • Utiliser file_exists avec $cheminFichier.
    • Si le fichier n'existe pas, retourner directement un tableau vide [] pour rester cohérent avec la promesse de la fonction. Cela permet au projet de démarrer même si aucun fichier JSON n'a encore été créé.
  4. Toujours dans lireJsonTableau, tenter de lire le contenu du fichier.
    • Utiliser file_get_contents avec $cheminFichier.
    • Stocker le résultat dans une variable $contenu.
    • Si file_get_contents retourne false, cela signifie que la lecture a échoué. Dans ce cas, retourner un tableau vide [] pour rester cohérent avec la promesse de la fonction.
  5. Toujours dans lireJsonTableau, gérer le cas où le contenu est vide.
    • Le fichier peut exister mais contenir une chaîne vide, ou seulement des espaces et retours à la ligne.
    • Utiliser trim sur $contenu pour retirer les potentiels espaces en début et en fin de chaîne.
    • Si le résultat de trim est une chaîne vide, retourner [] pour rester cohérent avec la promesse de la fonction.
  6. Toujours dans lireJsonTableau, convertir le JSON en tableau PHP.
    • Utiliser json_decode avec deux arguments :
      • Premier argument, le contenu JSON $contenu.
      • Deuxième argument, true pour obtenir un tableau associatif plutôt qu'un objet. Cela correspond au type de données manipulées dans le projet.
    • Stocker le résultat dans une variable $data.
    • Vérifier avec is_array que $data est bien un tableau. Si ça n'est pas le cas, retourner un tableau vide []. Cela couvre le cas d'un JSON invalide, mais aussi le cas où le JSON est valide mais ne représente pas un tableau.
    • Si $data est bien un tableau, le retourner. C'est ce tableau qui sera utilisé ensuite par les autres fonctions du projet.
  7. Tester la lecture sur un fichier inexistant.
    • Dans index.php, inclure src/chemins.php et src/json.php avec require_once.
    • Construire un chemin fictif dans data (ex.: getDossierData() . '/fichier_inexistant.json').
    • Appeler lireJsonTableau avec ce chemin et stocker le résultat dans une variable $resultat.
    • Afficher le tableau avec print_r. Vous devez obtenir un tableau vide, car le fichier n'existe pas.
  8. Tester la lecture sur un fichier existant dans le dossier imports.
    • Dans index.php, construire un chemin vers un fichier JSON réel du dossier imports/exemple-liste.json.
    • Pour construire le chemin, repartir de la racine du projet avec getRacineProjet(), puis ajouter /imports/exemple-liste.json.
    • Appeler lireJsonTableau avec ce chemin, puis stocker le résultat dans une variable $listeImport.
    • Afficher le tableau avec print_r. Vous devez obtenir un tableau contenant les valeurs du fichier JSON.

Étape 05

  1. Dans src/json.php, créer une fonction nommée ecrireJsonTableau. Elle permettra d'enregistrer un tableau PHP dans un fichier JSON. Cette fonction sera utilisée pour créer ou mettre à jour liste.json, restants.json et historique.json.
    • La fonction reçoit un paramètre $cheminFichier de type string. Il représente le chemin du fichier JSON à écrire (ex.: data/listes/abc123/historique.json).
    • La fonction reçoit un paramètre $data de type array. Il représente les données PHP à enregistrer au format JSON.
    • La fonction ne retourne rien, son rôle est uniquement d'écrire sur le disque.
  2. Dans ecrireJsonTableau, convertir le tableau en JSON.
    • Utiliser json_encode avec les options suivantes.
      • JSON_PRETTY_PRINT pour obtenir un fichier lisible à l'oeil humain. Cela aide à vérifier le contenu directement dans l'éditeur de code.
      • JSON_UNESCAPED_UNICODE pour garder les caractères comme é ou à. Ainsi, les fichiers restent lisibles.
    • Stocker le résultat dans une variable $json.
    • Si $json vaut false, remplacer sa valeur par la chaîne '[]'. Ainsi, vous écrivez toujours un JSON valide, même si l'encodage a échoué.
  3. Toujours dans ecrireJsonTableau, écrire le JSON dans le fichier.
    • Utiliser file_put_contents avec le chemin de destination stocké dans $cheminFichier et le nouveau contenu au format JSON stocké dans $json.
    • Cette écriture remplace entièrement le contenu du fichier. C'est utile ici, car on veut enregistrer l'état complet d'une liste à un instant donné.
  4. Tester l'écriture puis la relecture.
    • Dans index.php, préparer un tableau simple, avec trois chaînes, puis le stocker dans une variable nommée $aEcrire.

    Exemple de tableau :

    
                                <?php
                                $aEcrire = [
                                    'pomme',
                                    'banane',
                                    'cerise'
                                ];
                            
    • Construire un chemin vers un fichier de test dans le dossier import (ex.: getRacineProjet() . '/import/testJson.json').
    • Appeler ecrireJsonTableau avec le chemin de test et le tableau $aEcrire.
    • Ouvrir le fichier testJson.json dans votre éditeur. Vérifier qu'il est lisible grâce à l'indentation et que les caractères spéciaux sont bien présents.
    • Appeler ensuite lireJsonTableau sur le même chemin. Stocker le résultat dans une variable $relecture.
    • Afficher $relecture avec print_r. Vous devez retrouver le même tableau.

Étape 06

Préparer l'arborescence minimale de stockage. L'objectif est que le projet puisse créer automatiquement ses dossiers de travail avant d'essayer de lire ou d'écrire des fichiers JSON. À la fin de cette étape, les dossiers data et data/listes doivent exister sur le disque.

  1. Dans src/listes.php, activer le typage strict.
  2. Dans src/listes.php, inclure les dépendances nécessaires :
    • chemins.php car la fonction va construire des chemins comme data et data/listes.
    • creerDossier.php car la fonction va créer des dossiers sur le disque.
    • json.php car les étapes suivantes vont lire et écrire des fichiers JSON.
  3. Dans src/listes.php, créer une fonction nommée initialiserStockage. La fonction ne reçoit aucun paramètre. Elle ne retourne rien. Son rôle est de s'assurer que le projet dispose bien des dossiers nécessaires pour enregistrer ses données.
  4. Dans initialiserStockage, créer d'abord le dossier data.
    • Obtenir le chemin du dossier en appelant getDossierData(). Ce dossier servira à stocker toutes les données du programme sur le disque.
    • Appeler creerDossier avec ce chemin et récupérer son retour dans une variable $okData.
    • Si $okData vaut false, afficher le message suivant. Impossible de créer le dossier data. Dans ce cas, arrêter immédiatement la fonction avec return;. Le but est de ne pas continuer si le stockage n'est pas prêt.
  5. Toujours dans initialiserStockage, créer ensuite le dossier data/listes.
    • Obtenir le chemin du dossier en appelant getDossierListes(). Ce dossier regroupera toutes les listes importées.
    • Appeler creerDossier avec ce chemin et récupérer son retour dans une variable $okListes.
    • Si $okListes vaut false, afficher le message suivant. Impossible de créer le dossier listes. Dans ce cas, arrêter immédiatement la fonction avec return;.
  6. Tester initialiserStockage.
    • Dans index.php, inclure src/listes.php.
    • Si le dossier data existe déjà, le supprimer.
    • Appeler initialiserStockage().
    • Vérifier que les dossiers data et data/listes ont bien été créé par la fonction.
  7. Relancer le script une deuxième fois pour s'assurer que les messages d'erreur ne s'affichent pas si les dossiers existent déjà.

Étape 07

Réinitialiser un cycle de tirage pour une liste. L'objectif est de repartir sur un cycle propre à partir de la liste officielle. À la fin de cette étape, la fonction doit être capable de recopier liste.json vers restants.json et de vider historique.json.

  1. Dans src/listes.php, créer une fonction nommée reinitialiserCycle.
    • La fonction reçoit un paramètre $idListe de type string. Cet identifiant correspond au nom du sous-dossier de la liste (ex.: 2025-2026-bes-webdev-1ere).
    • La fonction ne retourne rien. Son rôle est de mettre à jour les fichiers JSON de travail de cette liste.
  2. Dans reinitialiserCycle, charger la liste officielle. C'est la version importée au départ, celle qui sert de référence. Elle ne doit jamais être modifiée pendant les tirages, car les tirages doivent uniquement modifier la copie de travail.
    • Construire le chemin de liste.json en passant $idListe lors de l'appel à la fonction getCheminListeJson().
    • Lire ce fichier avec la fonction lireJsonTableau. Pour cela, passer le chemin obtenu à l'étape précédente en argument de la fonction. Stocker le tableau retourné dans une variable nommée $liste.
  3. Copier la liste officielle dans la copie de travail restants.json. Ce fichier servira de liste de tirage pour le cycle en cours. À chaque tirage, l'élément choisi sera retiré de ce fichier afin d'éviter les doublons, et l'état du cycle restera mémorisé sur le disque.
    • Construire le chemin de restants.json en passant $idListe lors de l'appel à la fonction getCheminRestantsJson().
    • Écrire le tableau $liste dans restants.json avec la fonction ecrireJsonTableau. Pour cela, passer le chemin construit au point précédent en premier argument, puis passer $liste en second argument. Ainsi, restants.json démarre comme une copie exacte de la liste officielle (liste.json), prête à être modifiée par les tirages.
  4. Vider l'historique historique.json. Ce fichier sert à mémoriser l'ordre des tirages. Lorsqu'on redémarre un cycle, on doit repartir avec un historique vide, sinon on mélangerait les anciens tirages avec ceux du nouveau cycle.
    • Construire le chemin de historique.json en passant $idListe lors de l'appel à la fonction getCheminHistoriqueJson(). Ce chemin pointe vers le fichier qui enregistre toutes les valeurs tirées, dans l'ordre.
    • Écrire un tableau vide [] dans historique.json avec la fonction ecrireJsonTableau. Pour cela, passer le chemin construit au point précédent en premier argument, puis passer un tableau vide en second argument. Ainsi, le fichier historique.json est remis à zéro et le nouveau cycle démarre sans trace des anciens tirages.
  5. Tester reinitialiserCycle.
    • Dans index.php, inclure src/listes.php.
    • Toujours dans index.php, appeler initialiserStockage(). Le dossier data et le dossier data/listes doivent exister avant de travailler sur une liste.
    • Choisir un identifiant de test 'listeEtape07'. Cet identifiant représentera le nom du dossier de la liste dans data/listes.
    • Préparer une liste officielle de test sur le disque.
      • Créer le dossier de la liste à partir de son identifiant unique data/listes/listeEtape07 s'il n'existe pas encore.
      • Copier le fichier de test situé dans imports/exemple-liste.json, le coller dans le dossier venant d'être créé (data/listes/listeEtape07) et le renommer en liste.json.
      • À ce stade, vous devez donc avoir ce fichier sur le disque data/listes/listeEtape07/liste.json. C'est ce fichier que reinitialiserCycle utilisera comme référence.
    • Dans index.php, appeler reinitialiserCycle en lui passant l'identifiant de test 'listeEtape07'.
    • Vérifier sur le disque que la fonction a bien créé les fichiers du cycle.
      • Ouvrir data/listes/listeEtape07/restants.json. Ce fichier doit contenir la même liste que data/listes/listeEtape07/liste.json, car restants.json vient d'être recréé comme copie de travail.
      • Ouvrir data/listes/listeEtape07/historique.json. Ce fichier doit contenir un tableau vide [], car l'historique vient d'être remis à zéro.

Étape 08

Importer une liste depuis un fichier JSON externe. L'objectif est d'automatiser tout ce que vous venez de faire à la main. Créer le dossier de la liste à partir de son identifiant, copier la liste d'origine dans liste.json, puis préparer automatiquement le cycle en créant aussi restants.json et historique.json. À la fin de cette étape, un seul appel doit suffire à mettre en place ces trois fichiers pour une liste.

  1. Dans src/listes.php, créer une fonction nommée importerListeDepuisFichier.
    • La fonction reçoit un premier paramètre $idListe de type string. Cet identifiant servira à nommer le dossier de la liste (ex.: data/listes/classe1).
    • La fonction reçoit un second paramètre $cheminSourceJson de type string. Ce chemin correspond au fichier JSON externe à importer, par exemple imports/exemple-liste.json.
    • La fonction ne retourne rien. Elle écrit des fichiers sur le disque.
  2. Dans importerListeDepuisFichier, créer le dossier de la liste si nécessaire. L'idée est que l'identifiant $idListe corresponde à un sous-dossier dans lequel on va ranger les 3 fichiers JSON de cette liste. Ainsi, chaque liste importée possède son propre espace de stockage sur le disque.
    • Construire le chemin du dossier de la liste en passant $idListe lors de l'appel à la fonction getDossierListe(). Le chemin retourné aura la structure suivante : data/listes/{idListe}.
    • Appeler la fonction creerDossier en lui passant ce chemin. Stocker la valeur retournée dans une variable nommée $okListe.
      • Si creerDossier retourne true, le dossier existe déjà ou il a été créé avec succès.
      • Si creerDossier retourne false, le dossier n'a pas pu être créé (ex.: chemin invalide ou de droits insuffisants).
    • Si $okListe vaut false, afficher le message suivant dans le terminal. Impossible de créer le dossier listes. Dans ce cas, arrêter immédiatement la fonction avec return. Le but est de ne pas continuer l'import si l'emplacement de stockage n'existe pas.
  3. Charger le contenu du JSON externe. Ce fichier externe représente la liste brute à importer (liste de prénoms ou de mots). L'objectif est d'obtenir un tableau PHP exploitable pour pouvoir ensuite l'enregistrer proprement dans le stockage du projet.
    • Lire le fichier source avec la fonction lireJsonTableau. Pour cela, passer $cheminSourceJson en argument. Ce chemin correspond au fichier JSON externe tel qu'il a été fourni lors de l'appel à importerListeDepuisFichier.
    • Stocker le tableau retourné dans une variable nommée $liste. Si le fichier est vide, absent ou invalide, la fonction retournera simplement un tableau vide, ce qui évite de faire planter le programme.
  4. Enregistrer la liste officielle. L'objectif est d'enregistrer une version stable de la liste, qui servira de référence. Cette version ne doit jamais être modifiée pendant les tirages.
    • Construire le chemin de liste.json en passant $idListe lors de l'appel à la fonction getCheminListeJson(). Le chemin retourné aura la structure suivante : data/listes/{idListe}/liste.json.
    • Écrire le tableau $liste dans ce fichier avec la fonction ecrireJsonTableau. Pour cela, passer le chemin de liste.json en premier argument, puis passer $liste en second argument. Ainsi, le projet garde une copie officielle de la liste importée, prête à servir de point de départ pour les cycles.
  5. Préparer le cycle. L'objectif est de créer immédiatement les fichiers nécessaires aux tirages persistants. On veut pouvoir tirer des éléments sans modifier la liste officielle, et garder une trace de l'ordre des tirages.
    • Appeler reinitialiserCycle en lui passant $idListe. Cette fonction va utiliser le fichier liste.json situé dans le dossier $idListe comme référence, puis créer ou remettre à jour les deux fichiers suivants :
      • restants.json qui devient la copie de travail du cycle en cours.
      • historique.json qui est remis à zéro pour repartir sur un cycle propre.
  6. Tester l'import. L'objectif est de vérifier qu'un simple appel crée bien toute la structure d'une liste, sans devoir créer les dossiers et copier les fichiers à la main.
    • Dans index.php, inclure src/listes.php.
    • Appeler d'abord initialiserStockage() pour créer les dossiers permettant de stocker les listes (data et data/listes).
    • Appeler ensuite importerListeDepuisFichier en lui passant deux arguments.
      • Comme identifiant, utiliser 'listeEtape08'. Cet identifiant déterminera le nom du dossier créé dans data/listes.
      • Comme chemin source, utiliser le fichier JSON de test : 'imports/exemple-liste.json'.
  7. Vérifier sur le disque. Après exécution, vous devez voir apparaître un dossier data/listes/listeEtape08 contenant les fichiers suivants :
    • liste.json qui correspond à la liste officielle importée.
    • restants.json qui correspond à la copie de travail du cycle en cours.
    • historique.json qui correspond à l'historique des tirages, vide juste après l'import.
  8. Ouvrir les fichiers dans VS Code. L'objectif est de vérifier que les contenus correspondent bien au rôle de chaque fichier.
    • Ouvrir liste.json et vérifier qu'il contient la liste importée.
    • Ouvrir restants.json et vérifier qu'il contient exactement la même liste. À ce stade, aucun tirage n'a encore eu lieu, donc les deux fichiers doivent être identiques.
    • Ouvrir historique.json et vérifier qu'il contient un tableau vide [].

Étape 09

  1. Réaliser un tirage aléatoire sans doublon sur un cycle. À chaque tirage, un élément doit être retiré de restants.json, puis ajouté à l'historique.
  2. Dans src/tirage.php, activer le typage strict.
  3. Inclure les dépendances suivantes :
    • chemins.php
    • json.php
  4. Créer la fonction tirerSansDoublon. Cette fonction servira à tirer une valeur au hasard dans une liste, sans jamais retomber deux fois sur la même valeur pendant un même cycle.
    • Elle reçoit un paramètre $idListe sous forme de chaîne. Cet identifiant correspond au nom du dossier de la liste sur le disque, dans data/listes. (ex.: $idListe vaut listeDeTest, la fonction doit travailler dans le dossier data/listes/listeDeTest pour lire et mettre à jour restants.json et historique.json).
    • La fonction doit retourner une valeur qui représente l'élément tiré.
      • Tant qu'il reste des éléments dans restants.json, elle retourne une chaîne de caractères provenant du tableau généré à partir de ce fichier.
      • Quand restants.json est vide, cela signifie que tout a déjà été tiré une fois dans ce cycle. Dans ce cas, la fonction retourne null pour indiquer clairement qu'il n'y a plus rien à tirer.
  5. Dans cette fonction, charger les éléments encore disponibles depuis restants.json. Ce fichier représente la copie de travail du cycle en cours. C'est lui qui diminue à chaque tirage, afin d'éviter les doublons.
    • Construire d'abord le chemin de restants.json en passant $idListe lors de l'appel à la fonction getCheminRestantsJson().
    • Lire ensuite ce fichier avec la fonction lireJsonTableau. Pour cela, passer le chemin construit au point précédent en argument. Stocker le tableau retourné dans une variable nommée $restants.
    • Si le tableau $restants est vide. cela signifie qu'il n'y a plus rien à tirer dans ce cycle. Dans ce cas, retourner null.
  6. Tirer un élément au hasard, puis mettre à jour les fichiers du cycle. L'objectif est de retirer l'élément tiré de restants.json et de l'ajouter dans historique.json (l'ajout dans l'historique sera réalisé à l'étape suivante).
    • Choisir un index au hasard avec random_int.
      • Le premier argument doit être 0, car un tableau commence toujours à l'index 0.
      • Le deuxième argument doit correspondre au dernier index possible du tableau. Comme les index commencent à 0, le dernier index est toujours égal au nombre d'éléments du tableau moins 1. Ainsi, l'index tiré au hasard restera toujours dans les limites du tableau.
      • Stocker l'index obtenu dans une variable nommée $index.
    • Récupérer la chaîne tirée dans le tableau $restants.
      • Utiliser l'index $index pour lire l'élément correspondant.
      • Stocker la valeur récupérée dans une variable nommée $chaineTiree.
    • Retirer cette valeur du tableau $restants.
      • Utiliser array_splice. L'objectif est de supprimer 1 élément à la position $index.
      • Après cette suppression, le tableau $restants contient une valeur de moins. Cette mise à jour est ce qui empêche le doublon dans le cycle.
    • Sauvegarder le tableau $restants mis à jour dans restants.json.
      • Réutiliser le chemin de restants.json construit plus haut.
      • Appeler ecrireJsonTableau avec ce chemin en premier argument, puis le tableau $restants en second argument.
      • Le fichier restants.json est maintenant mis à jour sur le disque, ce qui rend le tirage persistant.
    • Retourner la valeur tirée. La fonction tirerSansDoublon doit donc retourner $chaineTiree tant qu'il reste des éléments, puis null lorsque le cycle est terminé.
  7. Tester un cycle complet. L'objectif est de vérifier que chaque tirage retourne une valeur différente, et que le cycle se termine en retournant null.
    • Dans index.php, inclure les fichiers nécessaires avec require_once.
      • src/listes.php
      • src/tirage.php
    • Appeler initialiserStockage() pour être sûr que le stockage existe (création automatique des dossiers data/listes).
    • Avec la fonction importerListeDepuisFichier, importer la liste de test (imports/exemple-liste.json) avec un nouvel identifiant unique 'listeEtape09'. Ainsi vous êtes sûr d'avoir la génération des fichiers liste.json, restants.json et historique.json dans le dossier data/listes/listeEtape09
    • Créer une boucle while qui appelle la fonction tirerSansDoublon en lui passant l'identifiant de la liste ('listeEtape09') à chaque tour.
      • Stocker la valeur retournée par tirerSansDoublon dans une variable nommée $nom.
      • Tant que $nom n'est pas null, afficher la valeur tirée echo "Tiré: $nom" . PHP_EOL.
    • Gérer la fin du cycle. L'objectif est que la sortie du test soit claire quand il n'y a plus rien à tirer.
      • Quand la boucle se termine, cela signifie que tirerSansDoublon a retourné null.
      • Après la boucle, afficher un message clair, par exemple "Cycle terminé: plus aucun élément à tirer." . PHP_EOL.
    • Vérifier les fichiers sur le disque. L'objectif est de confirmer que le tirage est bien persistant.
      • Ouvrir data/listes/listeEtape09/restants.json. Ce fichier doit maintenant contenir un tableau vide [], car tous les éléments ont été retirés pendant le cycle.
      • Vérifier aussi que data/listes/listeEtape09/liste.json n'a pas été modifié. Ce fichier doit toujours contenir la liste officielle complète.
    • Réinitialiser la liste pour pouvoir démarrer un nouveau cycle.
      • L'objectif est de remettre le cycle dans l'état de départ. Ainsi, restants.json redevient une copie complète de liste.json.
      • Appeler la fonction reinitialiserCycle en lui passant l'identifiant de la liste, par exemple 'listeEtape09'.
      • Vérifier ensuite sur le disque que la réinitialisation a bien eu lieu.
        • Ouvrir data/listes/listeEtape09/restants.json. Le fichier doit contenir toute la liste, comme liste.json.
        • Ouvrir data/listes/listeEtape09/historique.json. Le fichier doit être un tableau vide [].

Étape 10

Ajouter une entrée dans l'historique d'une liste. Le but est de garder une trace persistante de chaque tirage. Cette trace doit rester sur le disque, même si vous fermez le terminal et relancez le programme.

  1. Dans src/historique.php, activer le typage strict.
  2. Dans src/historique.php, inclure les dépendances nécessaires.
    • Inclure chemins.php, car on a besoin de construire le chemin vers historique.json à partir de l'identifiant de liste.
    • Inclure json.php, car on va lire et écrire un tableau dans un fichier JSON.
  3. Créer la fonction ajouterHistorique.
    • Cette fonction servira à ajouter une seule valeur à l'historique d'une liste suite au tirage aléatoire.
    • Elle doit recevoir deux paramètres :
      • $idListe sous forme de chaîne. Cet identifiant permet de retrouver le bon dossier dans data/listes.
      • $chaineTiree sous forme de chaîne. C'est la valeur à ajouter dans l'historique, dans l'ordre des tirages.
    • La fonction ne doit rien retourner. Elle doit simplement mettre à jour le fichier historique.json sur le disque.
  4. Dans cette fonction, construire le chemin vers le fichier historique.json.
    • Appeler la fonction getCheminHistoriqueJson en lui passant $idListe.
    • Stocker le chemin obtenu dans une variable $cheminHistorique. Ce chemin devrait avoir la structure suivante : data/listes/{idListe}/historique.json.
  5. Lire l'historique actuel depuis le disque.
    • Appeler lireJsonTableau avec $cheminHistorique.
    • Stocker le résultat dans une variable nommée $historique.
    • Vérifier que $historique est bien un tableau.
      • Si ce n'est pas un tableau, c'est que le fichier est vide, absent ou invalide. Dans ce cas, réassigner un tableau vide à $historique. Cela garantit que la suite du code manipule toujours un tableau.
  6. Ajouter la nouvelle valeur dans l'historique, puis sauvegarder.
    • Ajouter $chaineTiree à la fin du tableau $historique. L'ordre est important, car il doit correspondre à l'ordre des tirages.
    • Réécrire ensuite le fichier historique.json avec ecrireJsonTableau.
      • Passer $cheminHistorique en premier argument.
      • Passer le tableau $historique mis à jour en second argument.
  7. Retourner tout en haut du fichier src/tirage.php pour y inclure le fichier src/historique.php. La fonction tirerSansDoublon pourra ainsi faire appel à la fonction ajouterHistorique pour actualiser l'historique à chaque tirage.
    • Dans la fonction, juste avant l'instruction qui retourne l'élément tiré (return $chaineTiree), appeler la fonction ajouterHistorique en lui passant $idListe et $chaineTiree.
    • ajouterHistorique pourra ainsi ajouter cette valeur dans l'historique des tirages (historique.json).
  8. Tester tirerSansDoublon avec la mise à jour de l'historique. L'objectif est de vérifier que chaque tirage ajoute bien une entrée dans historique.json. Ensuite, réinitialiser le cycle pour vérifier que l'historique est bien vidé.
    • Dans index.php, inclure les fichiers nécessaires avec require_once.
      • src/listes.php
      • src/tirage.php
    • Appeler initialiserStockage(). Le but est de s'assurer que les dossiers data et data/listes existent avant d'importer une liste et d'écrire des fichiers JSON.
    • Importer une liste de test avec un identifiant neuf.
      • Appeler importerListeDepuisFichier avec comme identifiant 'listeEtape10' et comme source imports/exemple-liste.json.
      • L'objectif est d'avoir un dossier propre data/listes/listeEtape10 avec les trois fichiers liste.json, restants.json et historique.json.
    • Effectuer quelques tirages.
      • L'objectif principal est de vérifier que chaque tirage est bien enregistré dans historique.json.
      • Créer une boucle qui s'exécute 2 fois. À chaque tour, appeler tirerSansDoublon en lui passant l'identifiant 'listeEtape10'.
      • À chaque tour, stocker la valeur retournée dans une variable $nom, puis l'afficher dans le terminal avec un message clair : echo "Tiré: $nom" . PHP_EOL.
      • Ensuite, ouvrir le fichier data/listes/listeEtape10/historique.json. Vous devez y retrouver deux entrées. Elles doivent correspondre aux deux valeurs affichées dans le terminal, et elles doivent apparaître dans le même ordre.
      • Si une valeur affichée dans le terminal n'apparaît pas dans historique.json, ou si l'ordre ne correspond pas, c'est que l'enregistrement de l'historique n'est pas encore correct.
    • Réinitialiser le cycle pour vérifier que l'historique est bien vidé.
      • Appeler reinitialiserCycle en lui passant 'listeEtape10'.
      • Ouvrir ensuite data/listes/listeEtape10/historique.json. Le fichier doit être redevenu un tableau vide [].

Étape 11

Jusqu'ici, index.php servait de script de test. C'était pratique pour appeler vos fonctions une par une, vérifier les fichiers sur le disque, et comprendre le comportement du code étape après étape.

Maintenant, l'objectif change. Vous allez utiliser le projet comme un petit outil en ligne de commande. Au lieu de modifier index.php à chaque nouveau test, vous allez lancer directement des scripts dédiés dans bin, en leur passant des paramètres depuis le terminal.

L'intérêt est double. Vous évitez de réécrire du code de test à chaque fois. Et vous obtenez une façon claire d'utiliser l'application, comme un vrai programme (importer, tirer, historique, réinitialiser).

  1. Dans un script PHP lancé depuis le terminal (mode CLI), PHP fournit deux variables. Elles permettent de récupérer ce que vous avez tapé après php.
    • $argc contient le nombre total d'éléments reçus. Ce nombre inclut toujours le chemin du script lui-même. Cela sert à vérifier que l'utilisateur a bien fourni le bon nombre de paramètres.
    • $argv est un tableau de chaînes. Il contient chaque élément de la commande, dans l'ordre.
      • $argv[0] correspond au script tel qu'il a été indiqué dans la commande (ex.: si vous exécutez le script php ./index.php, alors $argv[0] vaut ./index.php).
      • $argv[1], $argv[2], etc. correspondent aux paramètres tapés après le script. Dans votre projet, cela servira surtout à passer un identifiant de liste ou un chemin vers le fichier JSON à importer. (ex.: si vous exécutez le script php ./index.php listeEtape11 ./import/exemple-liste.json, alors $argv[0] vaut './index.php', $argv[1] vaut 'listeEtape11' et $argv[0] vaut './import/exemple-liste.json').
  2. Faire un test simple avec index.php. Le but est juste de voir concrètement ce que PHP reçoit.
    • Dans index.php, afficher $argc, puis afficher le contenu de $argv avec print_r.
    • Dans le terminal, exécuter ensuite : php ./index.php bonjour 123. Vous simulez un script qui reçoit deux paramètres, comme vos scripts dans bin.
  3. Observer le résultat.
    • Vous devez constater que $argc vaut 3, car PHP compte le script + deux paramètres.
    • Vous devez aussi constater que $argv contient trois chaînes.
      • [0] le script tel que vous l'avez tapé (ex.: './index.php')
      • [1] le premier paramètre, ici 'bonjour'
      • [2] le second paramètre, ici '123'
    • Notez que tout est récupéré sous forme de chaîne de caractères. Si un script attend un entier, il devra le convertir. Dans votre projet, les identifiants de liste restent des chaînes, donc c'est parfait.
  4. Une fois ce test compris, arrêter d'utiliser index.php pour piloter l'application. À partir de maintenant, les tests et l'utilisation se font via les scripts du dossier bin. Vous passerez les paramètres directement dans la commande, plutôt que de modifier le code à chaque fois.

Étape 12

La commande importer va recevoir deux paramètres.

  • Un identifiant unique de liste.
  • Le chemin vers un fichier JSON externe à importer dans le système de tirage.

Elle crée automatiquement les dossiers de travail data et data/listes si ceux-ci n'existent pas encore. Ensuite, elle crée le dossier de la liste dans data/listes, enregistre la liste officielle, puis prépare le cycle. À la fin, vous obtenez directement les trois fichiers liste.json, restants.json et historique.json.

  1. Dans bin/importer.php, activer le typage strict avec declare(strict_types=1);.
    • Ce script va appeler des fonctions de src. Le typage strict aide à repérer plus tôt un appel incohérent, par exemple si une valeur inattendue est envoyée à une fonction.
    • Ici, vous allez manipuler des identifiants et des chemins. L'idée est de rester rigoureux sur le type "chaîne", même si les valeurs viennent du terminal.
  2. Dans ce fichier, inclure src/listes.php car nous aurons besoin de créer les dossiers de travail avec initialiserStockage et importer la liste avec importerListeDepuisFichier pour lui créer son propre dossier ainsi que ses 3 fichiers
  3. Appeler initialiserStockage() dès le début du script.
    • Le but est que la commande fonctionne même si le projet est "neuf". Si les dossiers data et data/listes n'existent pas encore, ils doivent être créés automatiquement.
    • Sans cet appel, la commande dépendrait d'une préparation manuelle sur le disque, ce qui serait fragile.
  4. Vérifier que la commande a reçu le bon nombre d'arguments.
    • Cette commande attend 2 informations tapées par l'utilisateur. Un identifiant de liste et un chemin vers un fichier JSON.
    • $argc compte aussi le script lui-même. Le total attendu est donc 3. Le script + l'identifiant + le chemin.
    • Si $argc n'est pas égal à 3, afficher un message d'usage clair indiquant le type de paramètres attendus echo "Usage: php bin/importer.php idListe chemin/vers/liste.json".
    • Arrêter le script avec la commande exit(1).
      • La fonction exit arrête immédiatement le script. Dès que PHP rencontre exit, il ne continue plus à exécuter les lignes suivantes. C'est utile ici, car si les arguments sont mauvais, la suite du script n'a plus de sens.
      • exit peut recevoir un nombre. Ce nombre est un "code de sortie" envoyé au terminal pour indiquer comment le script s'est terminé.
      • Par convention, exit(0) signifie "tout s'est bien passé". C'est le cas quand la commande a été utilisée correctement et que le travail est terminé.
      • Par convention, une valeur différente de 0 signifie "le script s'arrête à cause d'un problème". Ici, exit(1) signifie "erreur". Le choix de 1 est un choix simple et courant pour signaler un échec.
      • L'intérêt de ce nombre est que le terminal et d'autres scripts peuvent détecter automatiquement si la commande a réussi ou échoué. Dans un enchaînement de commandes, un outil peut décider d'arrêter la suite si une commande renvoie un code d'erreur (ex.: php bin/importer.php listeEtape12 imports/exemple-liste.json && php bin/tirer.php listeEtape12)
  5. Récupérer l'identifiant de liste.
    • Lire $argv[1]. C'est le premier paramètre tapé après le chemin du script script.
    • Stocker le résultat dans une variable nommée $idListe.
    • Refuser un identifiant vide. Si $idListe est une chaîne vide, afficher Erreur: idListe vide. puis arrêter le script avec exit(1).
    • Le but est d'éviter des chemins incohérents. Un identifiant vide pourrait faire viser le mauvais dossier dans data/listes.
  6. Récupérer le chemin du fichier JSON externe.
    • Lire $argv[2]. C'est le deuxième paramètre tapé après le script.
    • Vérifier que le fichier existe sur le disque avec file_exists.
    • Si le fichier est introuvable, afficher un message d'erreur Erreur: fichier introuvable: suivi du chemin ($cheminSource) puis arrêter le script avec exit(1).
  7. Importer la liste, puis confirmer.
    • Appeler importerListeDepuisFichier en lui passant $idListe et $cheminSource.
    • Afficher ensuite un message de confirmation OK. Liste importée: suivi de l'identifiant de la liste ($idListe)
  8. Tester la commande dans un cas normal.
    • Depuis la racine du projet, exécuter la commande suivante php bin/importer.php listeEtape12 imports/exemple-liste.json.
    • Vérifier que le terminal affiche bien OK. Liste importée: listeEtape12.
    • Vérifier ensuite sur le disque que le dossier data/listes/listeEtape12 existe.
    • Ouvrir ce dossier. Vous devez y trouver liste.json, restants.json et historique.json.
    • Ouvrir liste.json et restants.json. Les deux fichiers doivent contenir la liste importée. À ce stade, restants.json est une copie de départ du cycle.
    • Ouvrir historique.json. Il doit contenir un tableau vide, car aucun tirage n'a encore eu lieu.
  9. Tester la gestion des erreurs. Le but est de vérifier que le script guide correctement l'utilisateur, au lieu de s'arrêter sans explication.
    • Tester un appel sans arguments en lançant php bin/importer.php. Vous devez voir le message d'usage.
    • Tester un fichier introuvable en lançant php bin/importer.php classeX imports/inexistant.json. Vous devez voir une erreur claire qui affiche le chemin introuvable.
    • Tester un identifiant vide en passant uniquement des espaces (ex.: php bin/importer.php " " imports/exemple-liste.json). Vous devez voir Erreur: idListe vide..

Étape 13

La commande tirer va recevoir un seul paramètre. Il s'agit de l'identifiant unique correspond au nom du dossier de la liste dans data/listes. La commande va tirer une valeur au hasard sans doublon sur le cycle en cours (restants.json), puis afficher l'état du cycle.

  • Un identifiant unique de liste.

Concrètement, la commande lit la liste officielle (liste.json) pour connaître la taille totale du cycle, puis elle tire une valeur en modifiant la copie de travail (restants.json) et en enregistrant une trace dans historique.json. À chaque exécution, vous obtenez une sortie claire dans le terminal (la valeur tirée et le nombre de restants).

  1. Dans bin/tirer.php, activer le typage strict avec declare(strict_types=1).
  2. Dans ce fichier, inclure les dépendances nécessaires :
    • Inclure src/chemins.php et src/json.php, car la commande doit pouvoir construire les chemins des fichiers JSON et lire leur contenu.
    • Inclure src/tirage.php, car la commande doit tirer une valeur grâce à tirerSansDoublon.
  3. Vérifier que la commande a reçu le bon nombre d'arguments.
    • Cette commande attend une seule information tapée par l'utilisateur, l'identifiant de la liste.
    • $argc compte aussi le script lui-même. Le total attendu est donc 2, le script + l'identifiant.
    • Si $argc n'est pas égal à 2, afficher un message d'usage clair Usage: php bin/tirer.php idListe puis arrêter le script avec exit(1).
  4. Récupérer l'identifiant de la liste.
    • Lire $argv[1]. C'est le premier paramètre tapé après le chemin du script.
    • Nettoyer cette valeur avec trim, puis stocker le résultat dans une variable nommée $idListe.
    • Refuser un identifiant vide. Si $idListe est une chaîne vide, afficher Erreur: idListe vide. puis arrêter le script avec exit(1).
  5. Vérifier que la liste existe réellement sur le disque.
    • Construire le chemin du dossier de la liste avec getDossierListe($idListe).
    • Vérifier l'existence du dossier avec is_dir.
    • Si le dossier n'existe pas, afficher Erreur: la liste n'existe pas: suivi de $idListe, puis arrêter le script avec exit(1).
  6. Charger la liste officielle pour connaître la taille totale du cycle.
    • Construire le chemin de liste.json avec getCheminListeJson($idListe).
    • Lire ce fichier avec lireJsonTableau et stocker le résultat dans $liste.
    • Si count($liste) vaut 0, afficher Liste vide. puis arrêter le script avec exit(0).
  7. Tirer une valeur et afficher la progression.
    • Appeler tirerSansDoublon($idListe) et stocker le résultat dans $chaineTiree.
    • Si $chaineTiree vaut null, afficher un message indiquant que le cycle est terminé et inviter à réinitialiser pour débuter un nouveau cycle, puis arrêter le script avec exit(0).
    • Relire restants.json actualisé et afficher Tiré: ... suivi de la chaîne tirée ($chaineTiree) puis afficher le nombre d'éléments restants sur le nombre d'élément total Restants: X/Y.
      • Construire le chemin du fichier restants.json en appelant getCheminRestantsJson avec l'identifiant $idListe.
      • Relire le contenu de ce fichier en appelant lireJsonTableau avec le chemin obtenu à l'étape précédente. Stocker le tableau retourné dans une variable nommée $restants.
        • Après l'appel à tirerSansDoublon, le fichier restants.json a été modifié sur le disque. Un élément a été retiré du tableau, puis le fichier a été réécrit.
        • Relire restants.json permet d'afficher un compteur exact après le tirage, car on repart de l'état réellement enregistré sur le disque.
      • Afficher ensuite deux lignes dans le terminal :
        • Tiré: ... suivi de $chaineTiree pour affiché l'élément ayant été tiré aléatoirement.
        • Restants: X/Y pour indiquer la progression du cycle en affichant le nombre d'éléments restants et la taille totale de la liste officielle.
  8. Tester la commande.
    • Importer une liste de test php bin/importer.php listeEtape13 imports/exemple-liste.json.
    • Exécuter ensuite plusieurs fois php bin/tirer.php listeEtape13 et vérifier que le nombre de restants diminue.
    • Ouvrir data/listes/listeEtape13/historique.json et vérifier que les tirages sont ajoutés dans l'ordre.

Étape 14

La commande historique va recevoir un seul paramètre. Il s'agit de l'identifiant unique qui correspond au nom du dossier de la liste dans data/listes. La commande lit ensuite le fichier historique.json de cette liste et affiche son contenu dans le terminal, avec une numérotation, dans l'ordre des tirages.

  • Un identifiant unique de liste.

Si l'historique est vide, la commande doit simplement afficher Historique vide. et s'arrêter proprement. Si la liste n'existe pas, la commande doit refuser et afficher une erreur claire.

  1. Dans bin/historique.php, activer le typage strict avec declare(strict_types=1);.
  2. Inclure les dépendances nécessaires avec require_once.
    • src/chemins.php, car la commande doit pouvoir construire les chemins vers les fichiers JSON d'une liste.
    • src/json.php, car la commande doit lire le fichier historique.json sous forme de tableau.
  3. Vérifier que la commande a reçu le bon nombre d'arguments.
    • Cette commande attend une seule information tapée par l'utilisateur, l'identifiant de la liste.
    • $argc compte aussi le script lui-même. Le total attendu est donc 2, le script + l'identifiant.
    • Si $argc n'est pas égal à 2, afficher un message d'usage clair Usage: php bin/historique.php idListe puis arrêter le script avec exit(1).
  4. Récupérer et valider l'identifiant de la liste.
    • Lire $argv[1]. C'est le premier paramètre tapé après le chemin du script.
    • Nettoyer cette valeur avec trim, puis stocker le résultat dans une variable nommée $idListe.
    • Refuser un identifiant vide. Si $idListe est une chaîne vide, afficher Erreur: idListe vide. puis arrêter le script avec exit(1).
  5. Vérifier que la liste existe réellement sur le disque.
    • Construire le chemin du dossier de la liste avec getDossierListe($idListe). Ce chemin correspond au dossier attendu dans data/listes pour cette liste.
    • Vérifier l'existence de ce dossier avec is_dir.
    • Si le dossier n'existe pas, afficher Erreur: la liste n'existe pas: suivi de $idListe, puis arrêter le script avec exit(1).
  6. Charger l'historique depuis historique.json.
    • Construire le chemin de historique.json en appelant getCheminHistoriqueJson avec l'identifiant $idListe. Ce fichier garde la trace persistante des tirages, dans l'ordre.
    • Lire ce fichier avec lireJsonTableau en lui passant le chemin construit au point précédent. Stocker le tableau retourné dans une variable nommée $historique.
  7. Gérer le cas où il n'y a rien à afficher.
    • Si count($historique) vaut 0, afficher Historique vide..
    • Dans ce cas, arrêter le script avec exit(0). Ici, ce n'est pas une erreur, la commande a fonctionné et il n'y a simplement aucune entrée.
  8. Afficher chaque entrée de l'historique avec un numéro.
    • Parcourir le tableau $historique avec une boucle foreach qui donne à la fois l'index et la valeur.
    • Ignorer ce qui n'est pas une chaîne. Le but est d'éviter d'afficher des données inattendues si le fichier contient autre chose qu'une liste de textes.
    • Nettoyer chaque entrée avec trim avant affichage. Ignorer ensuite les entrées vides après nettoyage.
    • Afficher une ligne par entrée au format numéro + point + texte. Comme l'index commence à 0, afficher $i + 1 pour obtenir une numérotation qui commence à 1.
    • Terminer chaque ligne avec PHP_EOL pour obtenir un affichage propre dans le terminal.
  9. Tester la commande dans un cas normal.
    • Importer une liste de test avec la commande d'import, par exemple php bin/importer.php listeEtape14 imports/exemple-liste.json.
    • Effectuer quelques tirages sur cette liste, par exemple en exécutant plusieurs fois php bin/tirer.php listeEtape14.
    • Exécuter ensuite php bin/historique.php listeEtape14. Vous devez voir les valeurs tirées, dans l'ordre, avec une numérotation.
  10. Tester le cas d'un historique vide.
    • Importer une liste avec un nouvel identifiant, par exemple php bin/importer.php listeVideEtape14 imports/exemple-liste.json.
    • Sans faire de tirage, exécuter directement php bin/historique.php listeVideEtape14.
    • Vous devez obtenir Historique vide..
  11. Tester la gestion des erreurs.
    • Tester un appel sans identifiant en lançant php bin/historique.php. Vous devez voir le message d'usage.
    • Tester un identifiant qui ne correspond à aucune liste, par exemple php bin/historique.php listeInconnue. Vous devez voir l'erreur qui indique que la liste n'existe pas.
    • Tester un identifiant vide en passant uniquement des espaces, par exemple php bin/historique.php " ". Vous devez voir Erreur: idListe vide..

Étape 15

La commande reinitialiser va recevoir un seul paramètre. Il s'agit de l'identifiant unique qui correspond au nom du dossier de la liste dans data/listes. La commande remet ensuite le cycle dans l'état de départ. Concrètement, restants.json redevient une copie complète de liste.json, et historique.json est vidé.

  • Un identifiant unique de liste.

L'intérêt est de pouvoir relancer un nouveau cycle proprement quand tout le monde a déjà été tiré une fois. Au lieu de supprimer des fichiers à la main ou de recopier des données manuellement, un seul appel remet la liste dans un état "cycle neuf".

  1. Dans bin/reinitialiser.php, activer le typage strict avec declare(strict_types=1);.
    • Ce script va appeler des fonctions de src. Le typage strict aide à repérer plus tôt un appel incohérent, même si la valeur vient du terminal.
  2. Dans ce fichier, écrire un commentaire d'en-tête qui rappelle le rôle de la commande et son utilisation.
    • Indiquer que la commande réinitialise un cycle.
    • Rappeler clairement les deux effets attendus.
      • restants.json redevient une copie de liste.json.
      • historique.json est vidé.
    • Indiquer une ligne d'usage au format suivant php bin/reinitialiser.php idListe.
  3. Inclure les dépendances nécessaires :
    • Inclure src/chemins.php, car la commande doit pouvoir construire le chemin du dossier de la liste afin de vérifier son existence.
    • Inclure src/listes.php, car la commande va utiliser reinitialiserCycle pour remettre les fichiers du cycle dans leur état de départ.
  4. Vérifier que la commande a reçu le bon nombre d'arguments.
    • Cette commande attend une seule information tapée par l'utilisateur, l'identifiant de la liste.
    • $argc compte aussi le script lui-même. Le total attendu est donc 2, le script + l'identifiant.
    • Si $argc n'est pas égal à 2, afficher un message d'usage clair Usage: php bin/reinitialiser.php idListe puis arrêter le script avec exit(1).
    • Ici, exit(1) signifie que la commande s'arrête car elle a été mal utilisée. Le terminal reçoit un code d'erreur, ce qui permet à d'autres commandes ou scripts de détecter automatiquement l'échec.
  5. Récupérer l'identifiant de la liste.
    • Lire $argv[1]. C'est le premier paramètre tapé après le chemin du script.
    • Nettoyer cette valeur avec trim, puis stocker le résultat dans une variable nommée $idListe.
    • Refuser un identifiant vide. Si $idListe est une chaîne vide, afficher Erreur: idListe vide. puis arrêter le script avec exit(1).
    • Le but est d'éviter de viser un dossier incohérent sur le disque. Sans identifiant, la commande ne sait pas quelle liste réinitialiser.
  6. Vérifier que la liste existe réellement sur le disque.
    • Construire le chemin du dossier de la liste avec getDossierListe($idListe). Ce chemin correspond au dossier attendu dans data/listes pour cette liste.
    • Vérifier l'existence de ce dossier avec is_dir.
    • Si le dossier n'existe pas, afficher Erreur: la liste n'existe pas: suivi de $idListe, puis arrêter le script avec exit(1).
    • Cette vérification évite de réinitialiser "dans le vide". Une réinitialisation n'a de sens que si la liste a déjà été importée et qu'un dossier existe pour elle.
  7. Réinitialiser le cycle de la liste.
    • Appeler la fonction reinitialiserCycle en lui passant $idListe.
    • Cette fonction doit remettre les deux fichiers de cycle dans l'état attendu.
      • restants.json redevient une copie complète de liste.json, afin que la liste de tirage reparte de zéro.
      • historique.json redevient un tableau vide, afin d'effacer la trace des tirages précédents.
  8. Afficher une confirmation claire.
    • Après la réinitialisation, afficher un message de succès au terminal, par exemple OK. Cycle réinitialisé: suivi de l'identifiant $idListe.
    • Le but est que l'utilisateur sache immédiatement que la commande s'est bien terminée.
  9. Tester la commande dans un cas normal.
    • Importer une liste de test, par exemple php bin/importer.php listeEtape15 imports/exemple-liste.json.
    • Effectuer quelques tirages, par exemple en exécutant plusieurs fois php bin/tirer.php listeEtape15.
    • Ouvrir data/listes/listeEtape15/historique.json et vérifier qu'il contient déjà des valeurs. L'objectif est d'avoir une liste "en cours" avant de réinitialiser.
    • Exécuter ensuite php bin/reinitialiser.php listeEtape15. Vous devez voir un message de succès.
    • Vérifier sur le disque que la réinitialisation a bien eu lieu.
      • Ouvrir data/listes/listeEtape15/historique.json. Le fichier doit maintenant contenir un tableau vide [].
      • Ouvrir data/listes/listeEtape15/restants.json. Le fichier doit contenir toute la liste, comme liste.json.
    • Relancer un tirage après réinitialisation. Exécuter php bin/tirer.php listeEtape15 et vérifier que le cycle repart bien.
  10. Tester la gestion des erreurs.
    • Tester un appel sans identifiant en lançant php bin/reinitialiser.php. Vous devez voir le message d'usage.
    • Tester un identifiant vide en passant uniquement des espaces, par exemple php bin/reinitialiser.php " ". Vous devez voir Erreur: idListe vide..
    • Tester une liste inexistante, par exemple php bin/reinitialiser.php listeInconnue. Vous devez voir une erreur indiquant que la liste n'existe pas.

Nettoyage

Le fichier index.php était un outil de test temporaire. Une fois que les scripts du dossier bin fonctionnent, vous pouvez le supprimer ou le garder uniquement pour vos expérimentations.