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 n uniquement.

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 :

ContexteFormat recommandé
Base de données, JSON, APIn
Export CSV pour Excel (Windows)rn
Scripts shell Linuxn
Logs serveur multi-OSPHP_EOL
Email, headers HTTPrn

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.

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.

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 :

  1. Réception : $_POST['message'] peut contenir rn
  2. Normalisation : conversion en n uniquement
  3. Stockage DB : enregistrement en n
  4. Affichage HTML : nl2br(htmlspecialchars($texte))
  5. Export email : conversion en rn si besoin (norme RFC)

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

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/fin
  • rtrim($texte) : supprime uniquement en fin de ligne
  • preg_replace('/R+/', "n", $texte) : normalise tous types de retours en n (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
?>