Je l’ai vécu des dizaines de fois : un n qui s’affiche pas dans le navigateur, un export CSV qui plante sur Windows, ou des logs illisibles à cause de retours chariot mélangés. En PHP, gérer les sauts de ligne semble basique, mais ça cache des pièges cross-platform et HTML.
Dans ce guide, je vous montre quand utiliser n, r, rn ou PHP_EOL, comment afficher proprement en HTML avec nl2br(), et mes raccourcis pour éviter les bugs.
Comment sauter des lignes en PHP ?
En PHP, placer un n en début ou fin de ligne dans un echo ne change rien au résultat : les deux créent un saut de ligne dans le code source généré. L’important, c’est de comprendre que ce caractère ne sera visible que dans certains contextes.
Par exemple, echo "Ligne 1n"; et echo "nLigne 2"; produisent tous deux un retour à la ligne dans le source HTML, mais le navigateur l’ignore complètement. Pour que le saut de ligne s’affiche réellement dans une page web, il faudra soit une balise HTML (<br>), soit utiliser la fonction nl2br(), soit du CSS adapté avec white-space.
En revanche, dans un contexte CLI (ligne de commande), fichier texte ou log, ce n fonctionne parfaitement et casse effectivement la ligne à l’écran ou dans l’éditeur. C’est ce décalage entre sortie HTML et sortie texte qui génère la plupart des confusions.
Les bases du saut de ligne en PHP
Les retours chariot ne sont pas universels : chaque système d’exploitation a historiquement choisi sa propre convention. Comprendre ces différences évite les mauvaises surprises quand on développe sous Mac/Linux et qu’on déploie sur Windows, ou quand on génère des fichiers destinés à Excel.
La différence entre n, r et rn
Il existe trois caractères de contrôle pour les sauts de ligne :
- n (LF, Line Feed) : utilisé par Linux, Unix et macOS modernes.
- r (CR, Carriage Return) : utilisé par les anciens Mac (pré-OS X).
- rn (CRLF) : utilisé par Windows et les protocoles comme HTTP ou SMTP.
En PHP, ces séquences d’échappement fonctionnent uniquement entre guillemets doubles ("...") ou en syntaxe heredoc. Entre guillemets simples ('...') ou nowdoc, elles restent littérales.
Voici un exemple simple pour illustrer :
<?php
$ligne1 = "Ligne avec LFn";
$ligne2 = "Ligne avec CRLFrn";
$ligne3 = "Ligne avec CRr";
file_put_contents('test.txt', $ligne1 . $ligne2 . $ligne3);
?>
Selon l’éditeur ou l’OS, l’affichage du fichier test.txt variera. Mais attention : ces caractères ne « cassent » jamais la ligne en HTML sans balise <br> ou autre.
Quand utiliser quel caractère de retour chariot ?
Je vous recommande cette règle simple :
- Fichiers, CLI, logs : utilisez
PHP_EOL, qui s’adapte automatiquement à la plateforme. - Protocoles (email, headers HTTP) : forcez
rn(norme RFC). - Normalisation interne (BDD, JSON) : stockez en
nuniquement.
Pour les entrées utilisateur (formulaires), je normalise tout en n dès réception, puis je convertis selon la sortie : rn pour un export CSV Windows, n pour du JSON ou du stockage DB.
Mini mapping pratique :
| Contexte | Format recommandé |
|---|---|
| Base de données, JSON, API | n |
| Export CSV pour Excel (Windows) | rn |
| Scripts shell Linux | n |
| Logs serveur multi-OS | PHP_EOL |
| Email, headers HTTP | rn |
Mon conseil : évitez de mélanger r et n sans raison, sinon vous risquez des affichages bizarres ou des lignes collées dans certains éditeurs.
Afficher un saut de ligne dans le HTML avec PHP
Le navigateur ignore complètement les n du code source. Pour afficher un retour à la ligne visible dans une page web, il faut soit insérer des balises HTML (<br>, <p>), soit utiliser du CSS (white-space).
La fonction nl2br() expliquée avec exemples
La fonction nl2br() transforme automatiquement chaque n en balise <br> (ou <br /> en mode XHTML). C’est l’outil parfait pour afficher du contenu issu d’un textarea en conservant les retours à la ligne.
Exemple sécurisé :
<?php
$texte = $_POST['message'] ?? '';
echo nl2br(htmlspecialchars($texte, ENT_QUOTES, 'UTF-8'));
?>
Ici, htmlspecialchars() protège contre l’injection HTML, puis nl2br() insère les <br>. Attention : l’ordre est crucial. Si vous inversez (nl2br puis htmlspecialchars), les balises <br> seront échappées et affichées comme texte brut.
La fonction accepte un second paramètre is_xhtml (true par défaut) :
nl2br($texte, true)→<br />nl2br($texte, false)→<br>
Utiliser les balises HTML <br> directement
Parfois, il est plus simple d’insérer directement les <br> dans le code PHP, notamment pour du contenu généré côté serveur (emails HTML, fragments courts, templates).
Exemple :
<?php
echo 'Ligne 1<br>Ligne 2<br>Ligne 3';
?>
Alternative CSS pour afficher tel quel :
<p style="white-space: pre-line;"><?php echo htmlspecialchars($texte); ?></p>
La propriété white-space: pre-line conserve les retours à la ligne tout en fusionnant les espaces multiples. Idéal pour du contenu utilisateur simple sans balises.
Mon conseil : pour afficher des logs ou du code, utilisez <pre> qui respecte tous les espaces et retours. Pour du texte utilisateur riche, combinez nl2br() et échappement. Évitez d’imbriquer trop de <br> pour de longs textes : préférez les balises sémantiques (<p>, <ul>, etc.).
Cas pratiques et pièges à éviter
En audit de sites, je tombe régulièrement sur des bugs liés aux sauts de ligne : formulaires qui cassent la mise en page, exports CSV illisibles, ou logs qui mélangent plusieurs formats. Voici les erreurs les plus fréquentes et comment les éviter.
Pourquoi n ne s’affiche pas dans mon navigateur ?
HTML compresse tous les espaces et ignore complètement les n. Pour que le saut soit visible, il faut une balise (<br>, <p>, <pre>) ou du CSS (white-space).
Démonstration rapide :
<?php
echo "Ligne AnLigne B";
// Affiche : Ligne ALigne B (collé)
?>
Solution express pour tester :
<?php
header('Content-Type: text/plain; charset=UTF-8');
echo "Ligne AnLigne B";
// Affiche bien deux lignes
?>
En mode text/plain, le navigateur respecte les n. Sinon, utilisez nl2br() ou des balises HTML.
Mon conseil : avant de « debugger » vos sauts de ligne, vérifiez le contexte de sortie (HTML, JSON, text/plain). Ça évite de perdre du temps sur un faux problème.
Gérer les sauts de ligne dans les formulaires et textarea
Les navigateurs envoient souvent du rn (Windows) depuis les textarea, même sur Mac ou Linux. Pour éviter les incohérences, je normalise toujours côté serveur :
<?php
$texte = $_POST['message'] ?? '';
$texte = str_replace(["rn", "r"], "n", $texte);
// Maintenant tout est en n
?>
Pipeline complet :
- Réception :
$_POST['message']peut contenirrn - Normalisation : conversion en
nuniquement - Stockage DB : enregistrement en
n - Affichage HTML :
nl2br(htmlspecialchars($texte)) - Export email : conversion en
rnsi besoin (norme RFC)
Mon conseil : attention aux éditeurs WYSIWYG (TinyMCE, CKEditor) qui génèrent du HTML, pas des n. Dans ce cas, ne passez surtout pas par nl2br(), sinon vous doublerez les sauts de ligne.
Bonus : automatiser et optimiser vos retours chariot
Pour éviter les bugs cross-platform et nettoyer efficacement les données, j’utilise des constantes et fonctions natives de PHP qui gèrent automatiquement les différences d’OS et de protocoles.
Constante PHP_EOL : la solution cross-platform
PHP_EOL s’adapte automatiquement à l’OS du serveur : n sous Linux/Mac, rn sous Windows. C’est parfait pour les logs, fichiers temporaires, scripts CLI et exports.
Exemple :
<?php
$log = fopen('app.log', 'a');
fwrite($log, "[" . date('Y-m-d H:i:s') . "] Erreur serveur" . PHP_EOL);
fclose($log);
?>
Cas d’usage parfaits :
- Logs applicatifs
- Génération de fichiers CSV avec
fputcsv() - Scripts CLI (Symfony Console, Artisan, etc.)
- Fichiers temporaires traités par d’autres outils
Mon conseil : n’utilisez jamais PHP_EOL pour du HTML (préférez <br> ou nl2br()). Et respectez toujours rn pour les protocoles email et HTTP headers, même si votre serveur tourne sous Linux.
Supprimer ou remplacer les sauts de ligne (trim, preg_replace)
Pour nettoyer les entrées utilisateur ou compacter du texte, j’utilise ces fonctions :
trim($texte): supprime les espaces et sauts en début/finrtrim($texte): supprime uniquement en fin de lignepreg_replace('/R+/', "n", $texte): normalise tous types de retours enn(robuste, compatible Unicode)str_replace("n", ' ', $texte): remplace les sauts par des espaces (utile pour meta descriptions, exports sur une ligne)
Exemple de normalisation robuste :
<?php
$texte = $_POST['bio'] ?? '';
$texte = preg_replace('/R+/', "n", $texte); // Unifie tous les retours
$texte = trim($texte); // Nettoie début/fin
?>
Mon conseil : gardez toujours une version brute et une version normalisée de vos données. Et évitez les regex coûteuses sur de très gros blobs (plusieurs Mo) si un simple str_replace() suffit : c’est beaucoup plus rapide.
