Inclusion de Contenu de Fichiers avec Include et Require
Présentation
Lorsque vous développez des applications PHP, vous vous trouvez souvent confronté à la nécessité d'organiser votre code de manière propre et efficace. C'est là qu'interviennent les instructions include et require. Ces deux instructions vous permettent d'intégrer d'autres fichiers PHP dans votre script, offrant ainsi la possibilité de créer un code plus modulaire, plus facile à maintenir et réutilisable.
Les instructions include et require sont utilisées pour inclure le contenu d'un fichier externe dans votre script PHP. La principale différence entre les deux réside dans la manière dont elles gèrent les erreurs.
- include : Si le fichier inclus n'est pas trouvé, PHP émettra un avertissement (warning) mais continuera l'exécution du script. Cette instruction est utilisée lorsque l'inclusion du fichier est optionnelle, et que l'application peut continuer à fonctionner même si le fichier n'est pas trouvé.
- require : Si le fichier inclus n'est pas trouvé, PHP générera une erreur fatale (fatal error) et interrompra l'exécution du script. Cette instruction est utilisée lorsque l'inclusion du fichier est critique pour le fonctionnement de votre application.
Les instructions include_once et require_once sont similaires à include et require, mais elles vérifient si le fichier a déjà été inclus dans le script avant de l'inclure à nouveau. Cela évite les problèmes de duplication de code.
Principe de fonctionnement
Les quatre instructions include, include_once, require et require_once partagent le même principe. Elles demandent à PHP de lire un fichier puis d'en exécuter le contenu à l'endroit exact où l'instruction apparaît.
Pour se représenter le mécanisme, vous pouvez imaginer un copier-coller. Le contenu du fichier importé est injecté dans le fichier courant, puis PHP exécute l'ensemble comme s'il s'agissait d'un seul fichier.
Exemple avec un petit fichier contenant une variable. L'objectif n'est pas l'utilité métier, mais la compréhension du mécanisme.
Fichier "donnees.php"
<?php
$nom = 'Alice';
Fichier "index.php"
<?php
// Importer le contenu du fichier "donnees.php" à cet endroit.
require 'donnees.php';
// La variable $nom existe maintenant dans ce fichier,
// car elle a été définie dans le fichier importé.
echo $nom; // Affiche: Alice
Si on remplace mentalement l'instruction d'importation par le contenu du fichier, on obtient une version équivalente.
<?php
// --- Début du contenu de "donnees.php" ---
$nom = 'Alice';
// --- Fin du contenu de "donnees.php" ---
echo $nom; // Affiche: Alice
Un fichier inclus peut utiliser des variables qui ont été déclarées avant l'instruction d'inclusion dans le fichier appelant. Ces variables font partie du même contexte d'exécution et sont donc accessibles directement dans le fichier importé.
Cela permet de paramétrer le comportement d'un fichier inclus sans qu'il prenne de décision par lui-même. Le fichier inclus devient ainsi une brique réutilisable, pilotée par le script qui l'exécute.
Fichier "affichage.php"
<?php
// Ce fichier utilise une variable définie avant son inclusion.
echo "Bonjour : {$prenom} !";
Fichier "index.php"
<?php
// Définir une variable avant l'inclusion.
$prenom = 'Seb';
// Le fichier inclus peut utiliser cette variable.
include 'affichage.php'; // Affiche: Bonjour Seb !
Fichiers partagés et inclusion
Les instructions include et require servent à utiliser le contenu d'un fichier PHP dans un autre fichier. PHP lit le fichier indiqué et exécute son contenu à l'endroit où l'instruction apparaît.
Le choix entre les différentes instructions repose sur deux questions simples. Le fichier est-il obligatoire pour que le programme fonctionne. Doit-il être exécuté une seule fois ou plusieurs fois.
include
On utilise include lorsque le fichier est facultatif et qu'il peut être importer à plusieurs endroit du code durant la même exécution du programme. Si le fichier n'est pas trouvé, PHP affiche un avertissement, mais le programme continue à s'exécuter. Dans ce cas, l'instruction retourne false.
Dans l'exemple suivant, on utilise un petit fichier chargé d'afficher une ligne de séparation. On souhaite pouvoir l'utiliser plusieurs fois dans le même programme, avec des caractères différents.
Fichier "separateur.php"
<?php
// Ce fichier affiche une ligne de séparation.
// Les variables sont définies dans le fichier qui fait l'inclusion.
echo str_repeat($caractere, $longueur) . PHP_EOL;
Fichier "index.php"
<?php
// Première ligne de séparation
$caractere = '-';
$longueur = 30;
include 'separateur.php';
echo 'Début du programme' . PHP_EOL;
// Deuxième ligne de séparation
$caractere = '=';
$longueur = 30;
include 'separateur.php';
echo 'Fin du programme' . PHP_EOL;
Ici, include est adapté. Le fichier n'est pas indispensable et on souhaite qu'il soit exécuté à chaque inclusion. Avec include_once, seule la première ligne serait affichée.
require
On utilise require lorsque le fichier est indispensable. Si le fichier est introuvable, PHP arrête immédiatement le programme.
Dans l'exemple suivant, un fichier de configuration nécessaire au fonctionnement du programme. Ce fichier retourne un tableau de valeurs utilisées ailleurs.
Fichier "jeu.php"
<?php
// Configuration du jeu
return [
'PV_DEPART' => 30,
'DEGATS_MIN' => 2,
'DEGATS_MAX' => 6
];
Fichier "index.php"
<?php
// Sans ce fichier, le programme ne peut pas fonctionner.
$config = require 'jeu.php';
echo "PV de départ {$config['PV_DEPART']}" . PHP_EOL;
Fichiers partagés et inclusion unique
Dans un projet PHP, certains fichiers sont pensés comme des briques communes. Ils peuvent être utilisés par plusieurs scripts différents, chacun pouvant fonctionner de manière autonome.
Ces fichiers peuvent donc être inclus à plusieurs endroits du projet, parfois sans savoir s'ils ont déjà été chargés ailleurs. Les instructions se terminant par _once permettent d'éviter toute exécution multiple, tout en conservant cette souplesse d'organisation.
include_once
include_once fonctionne comme include, mais empêche d'exécuter le même fichier plusieurs fois pendant la même exécution du programme. Si le fichier a déjà été inclus, PHP l'ignore.
Ce cas apparaît souvent avec des outils de debug. Ces fichiers sont utiles pendant le développement, mais ils ne sont pas indispensables au fonctionnement du programme.
Fichier "debug.php"
<?php
// Affiche une valeur de manière lisible pendant le développement.
// La balise HTML <pre> est utilisée pour conserver les retours à la ligne
// et l'indentation générés par var_dump(), ce qui rend la sortie plus lisible.
// Ce type de fonction permet de centraliser l'affichage de debug
// et d'éviter de répéter le même code dans tout le projet.
function debug(mixed $valeur): void
{
echo PHP_EOL;
echo '--- DEBUG ---' . PHP_EOL;
var_dump($valeur);
echo '------------' . PHP_EOL;
}
Fichier "index.php"
<?php
$modeDebug = true;
// Le fichier de debug est optionnel.
// On le charge une seule fois pour éviter toute redéclaration.
if ($modeDebug)
{
include_once 'debug.php';
}
// On vérifie que la fonction existe avant de l'utiliser.
if (function_exists('debug'))
{
debug($_SERVER['PHP_SELF']);
}
require_once
require_once est utilisé lorsque le fichier est indispensable et qu'il ne doit être exécuté qu'une seule fois. C'est le cas le plus courant pour les fichiers contenant des fonctions.
Fichier "outils.php"
<?php
function lancerDe(int $min, int $max): int
{
return random_int($min, $max);
}
function appliquerDegats(int $pv, int $degats): int
{
$pv -= $degats;
if ($pv < 0)
{
$pv = 0;
}
return $pv;
}
Fichier "index.php"
<?php
require_once 'outils.php';
$config = require 'jeu.php';
$pv = $config['PV_DEPART'];
$degats = lancerDe($config['DEGATS_MIN'], $config['DEGATS_MAX']);
$pv = appliquerDegats($pv, $degats);
echo 'Dégâts ' . $degats . PHP_EOL;
echo 'PV restants ' . $pv . PHP_EOL;
En résumé
- include : facultatif, exécutable plusieurs fois.
- include_once : facultatif, exécutable une seule fois.
- require : indispensable, exécutable plusieurs fois.
- require_once : indispensable, exécutable une seule fois.
Le répertoire de travail courant
En PHP, de nombreuses opérations reposent sur des chemins relatifs. C'est notamment le cas lors de l'inclusion de fichiers avec require ou include, mais aussi pour la manipulation de fichiers (lecture, écriture, suppression, listage de dossiers, etc.).
Dans tous ces cas, le chemin relatif n'est pas interprété par rapport au fichier courant, mais par rapport à un contexte global appelé répertoire de travail courant.
Le répertoire de travail courant correspond au dossier depuis lequel le script PHP est lancé, et non au dossier dans lequel se trouve le fichier qui contient le code exécuté.
Pour observer ce comportement, nous allons utiliser la fonction getcwd(), qui retourne le chemin absolu du répertoire de travail courant.
Structure des fichiers
📁 monProjet/
├── 📄 index.php
└── 📁 src/
Si nous nous plaçons à la racine du projet monProjet/ dans le terminal et que nous exécutons le script avec la commande php ./index.php, le répertoire de travail courant correspond alors à la racine du projet.
Contenu du fichier "/index.php"
<?php
echo getcwd(); // Affiche : C:\projets-php\monProjet
Si l'on répète le test en se plaçant cette fois dans le sous-dossier src/ via le terminal, puis en exécutant le script avec la commande php ../index.php, le répertoire de travail courant change.
Il correspond désormais au dossier depuis lequel la commande a été lancée, c'est-à-dire le dossier src/.
Contenu du fichier "/index.php"
<?php
echo getcwd(); // Affiche : C:\projets-php\monProjet\src
Cet exemple montre que le répertoire de travail courant dépend uniquement du dossier depuis lequel le script est lancé, et peut donc varier sans que le code ne change. C'est ce comportement qui explique de nombreuses erreurs liées aux chemins relatifs.
Pourquoi les chemins relatifs posent problème
L'utilisation de chemins relatifs est une source fréquente d'erreurs, en particulier lorsque des fichiers inclus se trouvent dans des sous-dossiers et incluent à leur tour d'autres dépendances.
Pour comprendre ce comportement, observons un mini-projet composé de deux fichiers.
- index.php est situé à la racine du projet et sert de point d'entrée. Il inclut le fichier script.php situé dans le dossier src.
- script.php utilise la fonction scandir() avec le chemin ., qui représente le dossier courant. scandir() permet d'obtenir un tableau contenant les éléments (fichiers et dossiers) du dossier ciblé.
Structure des fichiers
📁 monProjet/
├── 📄 index.php
└── 📁 src/
└── 📄 script.php
Contenu du fichier "/index.php"
<?php
require './src/script.php';
Si nous exécutons le script en nous plaçant à la racine du projet dans le terminal, à l'aide de la commande php ./index.php, nous allons pouvoir observer l'influence du répertoire de travail courant sur l'interprétation des chemins relatifs.
Contenu du fichier "/src/script.php"
<?php
$elements = scandir('.');
print_r($elements);
/*
Résultat observé :
Array
(
[0] => .
[1] => ..
[2] => index.php
[3] => src
)
*/
Bien que ce code se trouve dans script.php, situé dans le dossier src, l'appel à scandir('.') liste le contenu du dossier depuis lequel le script a été lancé.
Dans cet exemple, le script a été lancé depuis la racine du projet. Le chemin relatif . est donc interprété à partir de ce dossier, et non à partir du dossier src.
Concrètement, PHP combine le répertoire de travail courant avec le chemin relatif fourni, ce qui conduit ici au chemin absolu : C:\projets-php\monProjet.
Si l'on souhaite lister le contenu du dossier src depuis script.php, il faut alors construire le chemin à partir du répertoire de travail courant.
Contenu du fichier "/src/script.php"
<?php
$elements = scandir('./src');
print_r($elements);
/*
Résultat observé :
Array
(
[0] => .
[1] => ..
[2] => script.php
)
*/
Cette écriture fonctionne, mais elle est contre-intuitive. Le fichier script.php se trouve déjà dans le dossier src, pourtant le chemin doit être reconstruit depuis le dossier de lancement du script.
Si l'on exécute maintenant le script en se plaçant dans le dossier /src via le terminal, à l'aide de la commande php ../index.php, le répertoire de travail courant change. Il correspond alors au dossier c:\projets-php\monProjet\src.
Dans ce contexte, le chemin relatif utilisé dans index.php, à savoir require './src/script.php';, est évalué à partir de ce nouveau répertoire de travail courant. PHP combine donc ce dossier avec le chemin relatif fourni, ce qui conduit au chemin absolu suivant : c:\projets-php\monProjet\src\src\script.php.
Ce chemin n'existe pas dans la structure du projet, ce qui provoque une erreur d'inclusion.
Cette démonstration met en évidence un point fondamental. Un chemin relatif ne possède pas de point d'ancrage fixe. Sa résolution dépend entièrement du répertoire de travail courant, lequel peut varier sans que le code ne change.
Dès lors, les chemins relatifs deviennent difficiles à anticiper. Ils doivent être ajustés en fonction du dossier depuis lequel le script est exécuté, ce qui rend le code peu flexible, difficile à maintenir et fortement dépendant du contexte d'exécution.
Récupérer le chemin absolu du dossier contenant le fichier PHP en cours
Pour éviter les problèmes liés aux chemins relatifs, PHP met à disposition une constante magique nommée __DIR__. Cette constante retourne dynamiquement le chemin absolu du dossier dans lequel se trouve le fichier PHP qui l'utilise, depuis la racine du disque jusqu'à ce dossier.
Contrairement aux chemins relatifs, la valeur de __DIR__ ne dépend pas du répertoire de travail courant. Elle est toujours calculée à partir de l'emplacement réel du fichier dans lequel elle est utilisée.
Contenu du fichier "/src/script1.php"
<?php
// Afficher la valeur de __DIR__.
echo __DIR__; // Affiche : c:\projets-php\monProjet\src
// __DIR__ pointe vers le dossier contenant ce fichier.
// On peut donc construire un chemin fiable vers une dépendance
// située dans ce même dossier.
require __DIR__ . '/script2.php';
Le chemin est désormais construit à partir de l'emplacement réel du fichier, indépendamment du dossier depuis lequel le script a été lancé.
Notez que la valeur retournée par __DIR__ ne se termine pas par un séparateur. Il est donc nécessaire d'ajouter explicitement / lors de la concaténation.
À propos de DIRECTORY_SEPARATOR
Dans du code PHP plus ancien ou dans certains projets orientés compatibilité multiplateforme, on rencontre parfois la constante DIRECTORY_SEPARATOR. Elle contient le séparateur de chemin propre au système d'exploitation : / sous Unix et \ sous Windows.
L'objectif de cette constante était d'assurer la compatibilité entre différents systèmes d'exploitation, à une époque où les séparateurs de chemin n'étaient pas gérés de manière uniforme par PHP.
Par exemple, pour cibler le fichier script.php situé dans le dossier src depuis le fichier index.php, il fallait concaténer le chemin en utilisant DIRECTORY_SEPARATOR à chaque niveau de l'arborescence.
Structure des fichiers
📁 monProjet/
├── 📄 index.php
└── 📁 src/
└── 📄 script.php
Contenu du fichier "index.php"
<?php
require __DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'script.php';
Pour raccourcir un peu les chemins, une pratique courante consistait à définir une constante globale plus courte, souvent nommée DS, égale à DIRECTORY_SEPARATOR. Le comportement ne changeait pas, seul le nom devenait plus court.
Contenu du fichier "index.php" avec une constante DS
<?php
define('DS', DIRECTORY_SEPARATOR);
require __DIR__ . DS . 'src' . DS . 'script.php';
Cette écriture reste parfaitement valide aujourd'hui, mais elle est plus verbeuse et moins lisible qu'une écriture utilisant directement / dans le chemin.
En pratique, PHP accepte désormais le caractère / pour la grande majorité des fonctions liées aux fichiers, y compris sous Windows. Dans un projet PHP web moderne, l'utilisation de DIRECTORY_SEPARATOR n'apporte donc généralement pas de bénéfice concret.
Il est alors courant d'écrire le même chemin de manière plus simple et plus lisible.
Contenu du fichier "index.php"
<?php
require __DIR__ . '/src/script.php';
Cette écriture est aujourd'hui la plus répandue dans les projets PHP web, car elle reste compatible avec les différents systèmes tout en améliorant la lisibilité du code.
Mise en garde sur certains chemins relatifs
Certains chemins relatifs peuvent sembler fonctionner même sans __DIR__, en particulier lorsqu'ils ne commencent ni par ./ ni par ../. Par exemple include 'script.php'.
Dans ce cas, PHP ne s'appuie pas sur un point de départ unique. Il peut rechercher le fichier dans plusieurs emplacements possibles avant de l'inclure. Le fichier effectivement chargé dépend alors du contexte d'exécution et de la structure du projet.
Ce comportement donne parfois l'impression que "ça marche", alors que le code repose sur une résolution implicite et fragile. Un changement de dossier de lancement, un déplacement de fichiers, ou une différence de configuration peut suffire à provoquer une erreur ou à inclure un autre fichier que prévu.
En pratique, pour gérer des dépendances entre fichiers, il est préférable d'ancrer les chemins à l'aide de __DIR__, afin d'obtenir un comportement explicite et prévisible.
Exercices
PHP: Chemins relatifs et répertoire de travail courant - Exo 01
Cet exercice porte sur les chemins de fichiers en PHP. Vous allez provoquer une erreur avec require, corriger les chemins sans utiliser __DIR__, puis constater que le code redevient fragile dès qu'on change le dossier depuis lequel on lance le script. Enfin, vous rendrez le projet stable en ancrant les chemins avec __DIR__.
Attendu
Le programme doit fonctionner dans deux situations. Quand il est lancé depuis la racine du projet. Quand il est lancé depuis un sous-dossier. Vous devez comprendre pourquoi la version sans __DIR__ dépend du dossier de lancement, et pourquoi la version avec __DIR__ ne dépend plus de ce contexte.
Structure
Créer un dossier nommé Exo-01-php-chemins-repertoire-travail, puis organiser les fichiers en respectant l'arborescence suivante.
📁 Exo-01-php-chemins-repertoire-travail/
├── 📄 index.php
└── 📁 src/
├── 📄 programme.php
├── 📁 affichage/
│ ├── 📄 titre.php
│ └── 📄 separateur.php
└── 📁 donnees/
└── 📄 message.php
Fichiers fournis
Copier les fichiers suivants à l'identique.
/src/affichage/separateur.php
<?php
echo str_repeat('-', 30) . PHP_EOL;
/src/affichage/titre.php
<?php
echo '=== EXO 01 ===' . PHP_EOL;
/src/donnees/message.php
<?php
return "Bonjour depuis message.php";
/src/programme.php
<?php
echo "programme.php démarré" . PHP_EOL;
/*
Dans ce fichier, tout est fait exprès pour déclencher un problème de chemins.
Objectif de départ
- Ce fichier est dans /src.
- Il charge des dépendances situées dans /src/affichage et /src/donnees.
- Les chemins sont écrits de manière "naturelle" comme si PHP partait du dossier /src.
*/
require './affichage/titre.php';
require './affichage/separateur.php';
$texte = require './donnees/message.php';
echo $texte . PHP_EOL;
require './affichage/separateur.php';
echo "programme.php terminé" . PHP_EOL;
/index.php
<?php
declare(strict_types=1);
echo "index.php démarré" . PHP_EOL;
require './src/programme.php';
echo "index.php terminé" . PHP_EOL;
Instructions
Le travail se fait dans /src/programme.php. Vous ne modifiez pas l'arborescence.
Étape 01
- Dans le terminal, se placer dans la racine du projet puis exécuter le fichier index.php avec la commande suivante : php ./index.php. À ce moment, le répertoire de travail courant est fixé. Il correspond au dossier depuis lequel vous lancez la commande. Dans ce contexte, la racine du projet C:/Exo-01-php-chemins-repertoire-travail.
-
Une erreur apparaît lors de l'exécution.
Elle se produit dans programme.php,
au moment où le script tente de charger
./affichage/titre.php.
- Ce comportement s'explique par l'utilisation de chemins relatifs. Bien que programme.php se trouve dans le dossier /src, le chemin ./affichage/titre.php est évalué à partir du répertoire de travail courant, c'est-à-dire la racine du projet. PHP cherche donc le fichier C:/Exo-01-php-chemins-repertoire-travail/affichage/titre.php, qui n'existe pas dans cette structure.
Étape 02
- Corriger les chemins dans /src/programme.php sans utiliser __DIR__. Vous devez uniquement adapter les chemins relatifs pour qu'ils fonctionnent quand vous lancez index.php depuis la racine du projet (C:/Exo-01-php-chemins-repertoire-travail).
- Tous les chemins du fichier programme.php doivent tenir compte du fait que l'évaluation démarre depuis la racine du projet. Vous devrez donc écrire des chemins qui repassent par src.
- Tester en relançant index.php depuis la racine. Vous devez obtenir une exécution complète, sans erreur.
- Relire les chemins obtenus. Ils fonctionnent, mais ils deviennent moins naturels à lire dans programme.php, car ils décrivent un trajet qui repart de la racine du projet au lieu de partir du dossier /src. Ces chemins restent donc dépendants du contexte d'exécution (le répertoire de travail courant) et ça n'est pas le seul problème...
Étape 03
- Dans le terminal, se placer dans le dossier /src.
- Exécuter à nouveau le script depuis ce nouveau répertoire de travail courant en lançant index.php avec la commande php ../index.php.
- Dans ce contexte, le programme peut à nouveau échouer. Les chemins précédemment corrigés étaient implicitement basés sur la racine du projet. En changeant le répertoire de travail courant, PHP ne résout plus les chemins relatifs de la même manière, ce qui entraîne des erreurs de chargement.
- Ce comportement montre qu'un chemin relatif sans point d'ancrage fiable dépend du dossier depuis lequel le script est lancé. Modifier ce point de départ modifie la lecture des chemins et peut rendre le programme instable. On ne doit donc pas faire confiance aux chemins relatifs lorsqu'ils dépendent du contexte d'exécution.
Étape 04
-
Revenir dans /src/programme.php
et remplacer les chemins relatifs par des chemins basés sur
__DIR__.
__DIR__ fournit le chemin absolu du dossier
dans lequel se trouve le fichier programme.php.
L'objectif est de construire des chemins qui partent du dossier réel de ce fichier,
indépendamment du répertoire depuis lequel le script est lancé.
- Notez que __DIR__ ne se termine pas par /, il faut donc concaténer explicitement ce séparateur lors de la construction du chemin.
-
Éxecuter le script depuis deux emplacement différent.
Dans le terminal :- Se placer à la racine du projet, puis exécuter php ./index.php.
- Se placer dans /src, puis exécuter php ../index.php.
PHP: include / require / include_once / require_once - Exo 02
Cet exercice porte sur l'import de fichiers PHP. Vous allez comparer include, require, include_once et require_once, en observant leur comportement face à deux situations très courantes.
Situation 1 inclure un fichier manquant.
Situation 2 inclure plusieurs fois le même fichier.
Attendu
À chaque étape, vous exécutez le script et vous observez. Vous devez être capable d'expliquer. Ce qui s'affiche. À quel moment l'exécution s'arrête ou continue. Pourquoi _once change le résultat.
Structure
Créer un dossier nommé Exo-02-php-include-require-once, puis organiser les fichiers et dossiers en respectant l'arborescence suivante.
📁 Exo-02-php-include-require-once/
├── 📄 index.php
└── 📁 src/
├── 📄 programme.php
├── 📁 affichage/
│ ├── 📄 titre.php
│ └── 📄 separateur.php
└── 📁 optionnel/
└── 📄 debug.php
Fichiers fournis
Copier les fichiers suivants à l'identique.
/src/affichage/separateur.php
<?php
echo str_repeat('-', 30) . PHP_EOL;
/src/affichage/titre.php
<?php
echo "=== EXO 02 ===" . PHP_EOL;
/src/optionnel/debug.php
<?php
echo "[debug] fichier debug.php chargé" . PHP_EOL;
/src/programme.php
<?php
echo "programme.php démarré" . PHP_EOL;
/*
Tout est volontairement en include au départ.
Objectifs du fichier
- Inclure plusieurs fois le même fichier pour provoquer des doublons.
- Inclure un fichier optionnel.
- Tenter d'inclure un fichier manquant.
*/
include __DIR__ . '/affichage/separateur.php';
echo "Partie 1 : Inclure deux fois le même fichier (doublon attendu)" . PHP_EOL;
include __DIR__ . '/optionnel/debug.php';
include __DIR__ . '/optionnel/debug.php';
include __DIR__ . '/affichage/separateur.php';
echo "Partie 2 : Inclure un fichier optionnel" . PHP_EOL;
include __DIR__ . '/optionnel/debug.php';
include __DIR__ . '/affichage/separateur.php';
echo "Partie 3 : Tenter d'inclure un fichier manquant" . PHP_EOL;
include __DIR__ . '/optionnel/inexistant.php';
echo "programme.php terminé" . PHP_EOL;
/index.php
<?php
declare(strict_types=1);
echo "index.php démarré" . PHP_EOL;
include __DIR__ . '/src/affichage/titre.php';
include __DIR__ . '/src/programme.php';
echo "index.php terminé" . PHP_EOL;
Instructions
Étape 01
- Exécuter index.php. Observer la sortie.
- Repérer la partie 1. Comme les instructions d'inclusion sont utilisées sans le suffixe _once, le même fichier peut être inclus plusieurs fois. Le message [debug] apparaît donc à chaque include.
-
Repérer la partie 3.
Le script poursuit son exécution jusqu'à afficher
programme.php terminé
puis index.php terminé,
même lorsqu'un fichier est manquant.
Ce comportement s'explique par l'utilisation de include,
qui génère un warning non bloquant. L'exécution continue, mais le contenu attendu n'a pas été chargé.
- Ce type d'inclusion est utilisé pour des fichiers facultatifs, comme des éléments d'affichage (ex.: bannière HTML) ou des outils de debug, dont l'absence ne doit pas empêcher le reste du programme de fonctionner.
Étape 02
- Dans la partie 1 du fichier programme.php, remplacer les deux inclusions de debug.php par include_once.
-
Exécuter index.php.
Observer la partie 1.
Le message [debug] n'apparaît plus qu'une seule fois,
car include_once empêche toute inclusion multiple
d'un même fichier au cours d'une même exécution.
Cette approche reste flexible, car le même fichier peut être inclus
à plusieurs endroits du projet, dans différents scripts,
sans risquer de doublon.
- Cela convient bien à des briques réutilisables, pensées pour fonctionner de manière indépendante.
Étape 03
- Dans la partie 3 du fichier programme.php, remplacer l'inclusion du fichier manquant (inexistant.php) par require.
-
Exécuter index.php.
L'exécution s'arrête dès que le fichier requis est manquant.
Ce comportement est dû à l'utilisation de require,
qui déclenche une erreur fatale lorsque le fichier ne peut pas être chargé.
Le programme est alors immédiatement interrompu,
et les messages de fin
programme.php terminé
et index.php terminé
ne s'affichent plus.
- Ce type d'inclusion est utilisé lorsque le fichier est indispensable au bon fonctionnement du programme.
Étape 04
- Dans la partie 2 du fichier programme.php, remplacer les inclusions de debug.php par require_once.
-
Exécuter index.php.
Le fichier debug.php n'est exécuté qu'une seule fois,
car require_once empêche toute inclusion multiple
durant la même exécution du programme.
Cette instruction garantit qu'un fichier n'est chargé qu'une seule fois,
ce qui évite les redéclarations.
- Elle est couramment utilisée pour des fichiers contenant des déclarations de fonctions ou de classes.
Exo-03-inclusion-frankenstein
Vous êtes le stagiaire du Dr Frankenstein. Il vous confie une mission simple. Préparer une main gauche complète, doigt par doigt, en respectant la chaîne de dépendances du laboratoire. Le but de l'exercice est de manipuler require, include, leurs variantes _once, et surtout de construire des chemins fiables avec __DIR__.
Attendu
L'exécution de laboratoire.php doit afficher un montage progressif de doigts, puis afficher la structure finale de la main sous forme de tableau. Le projet doit illustrer trois idées. Une dépendance indispensable se charge avec require_once. Une dépendance facultative se charge avec include. Un fichier peut être ré-exécuté à chaque tour de boucle via require pour obtenir un return différent.
Structure
Créer un dossier nommé Exo-03-inclusion-frankenstein, puis organiser les fichiers et dossiers en respectant l'arborescence suivante.
📁 Exo-03-inclusion-frankenstein/
├── 📄 laboratoire.php
├── 📁 accessoires/
│ └── 📄 bague.php
├── 📁 chambreFroide/
│ └── 📄 tupperwareDeDoigts.php
└── 📁 salleOperatoire/
├── 📄 assemblerDoigtsSurMain.php
└── 📄 assemblerMembres.php
Instructions
Vous allez construire le projet progressivement. Après chaque étape importante, exécuter laboratoire.php et observer ce qui s'affiche.
Étape 01
- Créer tous les dossiers et fichiers de la structure. À ce stade, ils peuvent être vides. L'objectif est d'avoir l'arborescence prête avant d'écrire du code.
Étape 02
-
Dans
salleOperatoire/assemblerMembres.php,
créer une fonction nommée
assemblerMembres.
La fonction reçoit trois paramètres :
- Un tableau $membreParent, représentant la main en cours de construction.
- Une chaîne $membreEnfant, représentant un doigt sous forme de texte.
- Une chaîne optionnelle $accessoire, pouvant aussi valoir null. L'accessoire est donc facultatif.
-
Dans la fonction
assemblerMembres,
ajouter un nouvel élément dans le tableau
$membreParent.
L'élément ajouté est un tableau associatif contenant :
- Une clé membreEnfant stockant la valeur de $membreEnfant.
- Une clé accessoire stockant la valeur de $accessoire si celle-ci est différente de null. Sinon, stocker la chaîne 'aucun'.
- Retourner le tableau $membreParent.
- Dans le fichier laboratoire.php, inclure temporairement le fichier assemblerMembres.php. Comme il s'agit d'un fichier contenant une déclaration de fonction indispensable au bon fonctionnement du script, utiliser require_once.
-
Toujours dans
laboratoire.php,
créer la structure de la main gauche sous la forme
d'un tableau associatif nommé
tupperware.
Ce tableau contient deux clés :
- La clé mainGauche, qui est un tableau vide destiné à stocker les doigts sous forme de chaînes de caractères.
- La clé accessoire, correspondant à l'accessoire de la main. Ici, la main n'a pas d'accessoire, on lui attribue donc la chaîne 'aucun'.
-
Tester la fonction
assemblerMembres :
- Extraire la main gauche du tableau tupperware et la passer comme membre parent via le premier paramètre.
- Passer un doigt à l'assembleur sous forme de chaîne 'doigt' via le second paramètre.
- Ne rien fournir pour le troisième paramètre, afin de vérifier que la fonction gère correctement l'absence d'accessoire.
- Si le test s'est bien déroulé, supprimer l'appel de test à la fonction assemblerMembres, la variable $mainAvecUnDoigt ainsi que l'affichage de test.
Étape 03
- Dans le fichier /accessoires/bague.php, retourner simplement une chaîne de caractères : return 'bague'.
- Tester temporairement ce fichier dans laboratoire.php. Inclure bague.php, stocker sa valeur de retour dans une variable $accessoireTemporaire, puis afficher le résultat avec echo.
- Si le test fonctionne comme prévu, supprimer tous les éléments de test dans laboratoire.php. Retirer la variable $accessoireTemporaire, l'inclusion temporaire, ainsi que le echo associé.
Étape 04
-
Dans le fichier /chambreFroide/tupperwareDeDoigts.php,
retourner une chaîne de caractères comme ceci :
return "doigt n°{$i}".
- Ce fichier sera inclus à l'intérieur d'une boucle lors de l'assemblage des doigts sur la main. La variable $i sera donc définie dans la fonction qui effectue cet assemblage, à savoir assemblerDoigtsSurMain, située dans le fichier du même nom.
- Le rôle de ce fichier n'est pas de décider du numéro du doigt, mais d'utiliser une information fournie par le script qui l'inclut. Cela illustre le fait qu'un fichier inclus s'exécute dans le contexte du code appelant.
- Tester temporairement ce fichier dans laboratoire.php. Déclarer une variable $i valant 3, inclure le fichier, puis stocker son retour dans une variable $doigtTemporaire. Afficher ensuite le résultat avec echo.
- Si le test fonctionne comme prévu, supprimer tous les éléments de test dans laboratoire.php. Retirer la variable $i, la variable $doigtTemporaire, l'inclusion temporaire, ainsi que le echo associé.
Étape 05
- Dans salleOperatoire/assemblerDoigtsSurMain.php, importer le plan d'assemblage assemblerMembres.php avec require_once puisqu'il s'agit d'un fichier comprenant une déclaration de fonction indispensable au bon fonctionnement du script.
-
Déclarer une fonction nommée assemblerDoigtsSurMain.
Elle reçoit deux paramètres.
- $main de type tableau. Il représente la main en cours d'assemblage.
- $nbrDoigts de type entier, avec la valeur par défaut 5. Par défaut, on fabrique une main à 5 doigts, mais on garde un paramètre pour tester une autre quantité.
- Dans la fonction, créer une boucle for qui compte de 1 jusqu'à $nbrDoigts.
- Dans la boucle, afficher un message de montage qui sera affiché pour chaque doigt : '🔨 Montage du doigt $i...' . PHP_EOL;
- Toujours dans la boucle, charger un doigt depuis /chambreFroide/tupperwareDeDoigts.php en utilisant require car les doigts sont nécessaires pour la greffe sans _once car le fichier doigt être inclu à chaque itération de la boucle. Stocker le doigt de l'itération courante dans une variable $doigt.
- On désire ajouter une bague pour chacun des doigts. Toujours dans la boucle, charger ensuite l'accessoire depuis /accessoires/bague.php en utilisant include puisque la bague n'est pas indispensable à la greffe, si le fichier n'est pas disponible, le script ne doit donc pas planter. Même remarque que pour l'inclusion du doigt, on utilise pas _once car le fichier bague être inclu à chaque itération de la boucle. Stocker la valeur retournée dans une variable nommée $bague.
- Gérer le cas où l'accessoire est introuvable. include retourne false si le fichier n'a pas pu être chargé. Comme nous allons passer $bague à la fonction assemblerMembres en troisième paramètre et que ce paramètre attend soit une chaîne de caractères (string) soit NULL, il faut convertir $bague en null si sa valeur vaut false .
-
Toujours au sein de la boucle et à la suite du code acutel, appeler assemblerMembres pour ajouter le doigt et l'accessoire à la main.
Passer donc les trois valeurs suivante à la fonction assemblerMembres :
- Premier argument : le membre parent situé dans la variable $main.
- Second argument : le membre enfant situé dans la variable $doigt.
- Troisième argument : l'accessoire situé dans la variable $bague.
assemblerMembres retourne un nouveau tableau. ]A chaque itération, réaffecter le résultat retourné par assemblerMembres dans $main. Il s'agit du tableau $main qui est à chaque itération actualisé avec le doigt et la bagues de l'itération courante. - À la fin de la fonction, en dehors de la boucle retourner le tableau $main actualisé avec tous ses doigts et ses bagues.
Étape 06
- Dans laboratoire.php, importer la dépendance indispensable /salleOperatoire/assemblerDoigtsSurMain.php avec require_once.
- Reprendre votre variable $tupperware (créée à l'étape 02).
- Sortir la main du tupperware ($tupperware['mainGauche']) et la passée à assemblerDoigtsSurMain lors de son appel. Réassigner la main du tupperware avec le tableau retourné par l'assembleur assemblerDoigtsSurMain.
- Afficher un titre (ex.: 'Résultat assemblage main : ') puis afficher la main complète avec print_r.
Étape 07
- Tester le projet en exécutant le fichier laboratoire.php. Un message de montage pour chaque doigt ainsi que le tableau final contenant 5 éléments devraient s'afficher.
- Renommer temporairement /accessoires/bague.php (ex.: en bague_OFF.php) afin de simuler son absence. Relancer ensuite laboratoire.php. Le script devrait continuer malgré un avertissement, et la main est quand même construite. Si nous avions utilisé require plutôt que include le script aurait cessé de fonctionner durant la boucle.
- Exécuter le script depuis un autre dossier du projet afin de vérifier que les chemins vers les fichiers sont stables. Dans le terminal, se placer dans /chambreFroide, puis lancer le laboratoire avec php ../laboratoire.php. Si de nouvelles erreurs apparaissent, c'est que certains chemins sont encore dépendants du répertoire de travail courant. Dans ce cas, construire les chemins d'inclusion à partir du dossier réel du fichier qui inclut, en utilisant la constante magique __DIR__.