Le WordPress d'aujourd'hui, décodé pour les développeurs

Thèmes

Une redirection ignorée à cause d’une ligne vide avant `<?php` en functions.php

Un appel à wp_redirect() placé au bon endroit, mais qui ne redirige jamais, sans la moindre erreur PHP visible. Le coupable est un caractère invisible avant la balise d'ouverture.

Par WordPress Développement • 23 février 2023 • 5 min de lecture • Aucun commentaire
Une redirection ignorée à cause d'une ligne vide avant `<?php` en functions.php

Pourquoi un appel à wp_redirect(), placé au bon endroit dans un hook template_redirect, ne redirige-t-il jamais l’utilisateur, sans la moindre trace d’erreur dans les journaux ni dans l’écran habituellement bavard de WordPress ? Le code semble correct, la condition qui déclenche la redirection est bien atteinte, un error_log() placé juste avant confirme même que la ligne est exécutée. Et pourtant, la page continue de s’afficher normalement.

Ce scénario, rencontré sur un thème classique dont le fichier functions.php avait été modifié par plusieurs personnes au fil des mois, cache une cause précise et redoutablement discrète : un ou plusieurs caractères présents avant la balise d’ouverture <?php, ou après la balise de fermeture ?> en fin de fichier.

Le symptôme : une redirection qui s’exécute mais ne redirige rien

Le code incriminé ressemble à ceci, et n’a rien d’anormal en apparence :

add_action( 'template_redirect', function () {
    if ( is_page( 'ancienne-page' ) ) {
        wp_redirect( home_url( '/nouvelle-page/' ), 301 );
        exit;
    }
} );

La fonction is_page() retourne bien true, l’instruction exit est atteinte, mais le navigateur affiche malgré tout le contenu de la page d’origine, parfois précédé d’un espace blanc supplémentaire en haut de la fenêtre.

Le diagnostic : des en-têtes HTTP déjà envoyés

wp_redirect() repose sur la fonction PHP native header(), qui doit impérativement être appelée avant tout envoi de contenu au navigateur. Or, dès qu’un caractère — un espace, une ligne vide, un caractère invisible d’encodage BOM (byte order mark) — se trouve en dehors des balises <?php ?> d’un fichier chargé avant le hook template_redirect, PHP considère ce caractère comme du contenu à afficher et l’envoie immédiatement au navigateur. Une fois cette sortie effectuée, les en-têtes HTTP sont considérés comme déjà envoyés, et tout appel ultérieur à header() échoue silencieusement : PHP ne lève une erreur « headers already sent » que si l’affichage des erreurs est activé, et cette erreur n’apparaît pas toujours dans les journaux si display_errors est désactivé en production.

L'essentiel à retenir : Un caractère avant <?php envoie une sortie avant les en-têtes HTTP ; wp_redirect() échoue silencieusement si les en-têtes sont déjà envoyés ; WP_DEBUG seul ne révèle pas ce type d'échec

Retrouver le caractère fautif

Le suspect le plus fréquent est une ligne vide laissée après la balise ?> à la fin du fichier functions.php, ou un espace introduit avant <?php lors d’un copier-coller depuis un éditeur de texte qui a conservé un caractère invisible. Un moyen fiable de le confirmer consiste à activer temporairement l’affichage des erreurs et à observer le message qui précède l’échec :

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_DISPLAY', true );

Le message attardé ressemble à : Warning: Cannot modify header information - headers already sent by (output started at .../functions.php:1). Le numéro de ligne indiqué — souvent la ligne 1 — pointe directement vers le fichier et l’endroit où la sortie a commencé.

Le correctif : supprimer la balise de fermeture PHP

La pratique recommandée dans les standards de codage de WordPress consiste à ne jamais fermer la balise PHP à la fin d’un fichier qui ne contient que du code PHP, précisément pour éviter ce genre d’incident :

<?php
// Fin du fichier functions.php, sans balise de fermeture ni ligne vide après.
add_action( 'template_redirect', function () {
    // ...
} );

Il faut également vérifier qu’aucun caractère BOM n’a été enregistré en tête de fichier, ce qui arrive fréquemment avec certains éditeurs configurés en encodage UTF-8 avec BOM plutôt qu’en UTF-8 sans BOM. La plupart des éditeurs modernes permettent de choisir explicitement l’encodage de sauvegarde dans leurs préférences.

Prévenir la récidive avec un outil d’analyse statique

Un outil comme PHP_CodeSniffer, configuré avec les règles du projet WordPress Coding Standards, détecte automatiquement la présence de code en dehors des balises PHP et peut être intégré à une étape de vérification avant chaque déploiement. Cela évite qu’un futur copier-coller, effectué par une autre personne de l’équipe, ne reproduise le même incident sur un autre fichier du thème.

  • Supprimer systématiquement la balise de fermeture ?> dans les fichiers 100 % PHP.
  • Enregistrer les fichiers en UTF-8 sans BOM.
  • Vérifier avec un éditeur hexadécimal ou xxd en cas de doute persistant sur les premiers octets du fichier.

En résumé

Une redirection qui s’exécute sans effet, sans message d’erreur visible en production, mérite de vérifier en priorité l’état des en-têtes HTTP avant de remettre en cause la logique métier du code. Le caractère fautif est souvent invisible à l’œil nu dans un éditeur classique, mais son effet est systématique : tant qu’il subsiste avant la première balise <?php d’un fichier chargé tôt dans le cycle de WordPress, aucune fonction basée sur header() ne pourra fonctionner correctement sur les pages concernées.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi