vendredi 25 septembre 2026

À propos

Contact

Extensions

Rewrite API : créer des URL personnalisées avec add_rewrite_rule

/annuaire/region/bretagne/artisan/12 : une URL métier que WordPress ne sait pas router nativement. La Rewrite API permet de la créer proprement, sans page statique bricolée.

Par Clément Hadrot • 5 janvier 2021 • 4 min de lecture • Aucun commentaire
Rewrite API : créer des URL personnalisées avec add_rewrite_rule

Un annuaire professionnel régional m’a demandé une URL de la forme /annuaire/bretagne/plombier/, filtrable par région et par métier, sans passer par des paramètres de requête classiques du type ?region=bretagne&metier=plombier. Une bonne partie des extensions bricolent ce genre de besoin avec des pages statiques et du contenu généré dynamiquement en PHP. La Rewrite API de WordPress permet une solution bien plus propre, directement intégrée au système de permaliens.

Déclarer la règle de réécriture

add_rewrite_rule() associe une expression régulière à une URL interne exploitable par WordPress, sous la forme d’une chaîne de requête classique. Elle doit être enregistrée sur le hook init.

add_action( 'init', 'annuaire_ajouter_regles_reecriture' );

function annuaire_ajouter_regles_reecriture() {
    add_rewrite_rule(
        '^annuaire/([^/]+)/([^/]+)/?$',
        'index.php?annuaire_region=$matches[1]&annuaire_metier=$matches[2]',
        'top'
    );
}

Le troisième argument, 'top', place la règle en tête de la liste plutôt qu’à la fin. C’est important : WordPress évalue les règles dans l’ordre, et une règle générique du cœur pourrait sinon intercepter l’URL avant que la vôtre ne soit testée.

Enregistrer les query vars associées

Une règle de réécriture qui pointe vers des variables de requête non enregistrées ne fonctionne pas : WordPress ignore silencieusement toute variable de $_GET qui ne figure pas dans sa liste blanche de query vars publiques.

L'essentiel à retenir : Une règle de réécriture doit toujours être associée à une ou plusieurs query vars enregistrées ; flush_rewrite_rules ne s'exécute qu'à l'activation, jamais à chaque chargement ; template_redirect est le bon endroit pour intercepter la requête finale
add_filter( 'query_vars', 'annuaire_ajouter_query_vars' );

function annuaire_ajouter_query_vars( $vars ) {
    $vars[] = 'annuaire_region';
    $vars[] = 'annuaire_metier';
    return $vars;
}

C’est l’erreur numéro un sur ce type de développement : la règle semble correcte, l’URL ne renvoie pas de 404, mais les valeurs de get_query_var( 'annuaire_region' ) restent obstinément vides. Neuf fois sur dix, c’est parce que le filtre query_vars a été oublié.

Intercepter la requête sur template_redirect

Une fois les query vars disponibles, il reste à décider quoi afficher. Deux approches possibles : rediriger vers un template personnalisé via template_include, ou construire la sortie directement sur template_redirect.

add_action( 'template_redirect', 'annuaire_afficher_page_filtree' );

function annuaire_afficher_page_filtree() {
    $region = get_query_var( 'annuaire_region' );
    $metier = get_query_var( 'annuaire_metier' );

    if ( empty( $region ) || empty( $metier ) ) {
        return;
    }

    $professionnels = annuaire_rechercher_professionnels( $region, $metier );

    if ( empty( $professionnels ) ) {
        global $wp_query;
        $wp_query->set_404();
        status_header( 404 );
        return;
    }

    annuaire_charger_template_resultats( $region, $metier, $professionnels );
    exit;
}

Gérer explicitement le cas d’une combinaison région/métier sans résultat avec set_404() évite d’afficher une page vide avec un code HTTP 200, ce qui serait trompeur autant pour les visiteurs que pour les moteurs de recherche.

Le piège du flush prématuré ou répété

Pour que les nouvelles règles soient prises en compte, WordPress doit régénérer sa table de règles de réécriture, une opération réalisée par flush_rewrite_rules(). C’est une fonction coûteuse, à réserver strictement à l’activation et à la désactivation de l’extension.

  • Ne jamais appeler flush_rewrite_rules() sur le hook init à chaque chargement de page : c’est l’erreur de performance la plus fréquente sur ce sujet
  • À l’activation, appeler d’abord la fonction qui enregistre les règles, puis flush_rewrite_rules(), jamais l’inverse
  • À la désactivation, appeler flush_rewrite_rules() seul suffit à nettoyer les règles devenues obsolètes
register_activation_hook( __FILE__, function () {
    annuaire_ajouter_regles_reecriture();
    flush_rewrite_rules();
} );

register_deactivation_hook( __FILE__, 'flush_rewrite_rules' );

Un flush systématique à chaque chargement masque un bug de développement plutôt qu’il ne le résout : si une règle ne fonctionne qu’après un flush manuel répété, c’est probablement qu’elle n’est pas enregistrée au bon moment.

Pour aller plus loin

La Rewrite API reste, huit ans après ses débuts, l’outil de référence pour créer des URL métier propres sans dépendre d’un plugin tiers de gestion de permaliens. Elle demande de la rigueur sur l’ordre des opérations — règle, query vars, puis flush une seule fois — mais offre en échange des URL lisibles, indexables, et parfaitement intégrées au reste du système de permaliens de WordPress.

Partager :

À propos de l'auteur

Clément Hadrot

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

Voir tous ses articles

Dans la même veine

À lire aussi