ITSkillsCenter
WordPress

Tutoriel : Les hooks WordPress (actions et filtres) expliqués

9 min de lecture

Les hooks : le système nerveux de WordPress

Les hooks sont le mécanisme fondamental qui rend WordPress extensible. Chaque fois que WordPress fait quelque chose — charger une page, enregistrer un article, envoyer un email, afficher un menu — il déclenche des hooks auxquels vous pouvez vous accrocher pour ajouter, modifier ou supprimer des comportements. Comprendre les hooks, c’est comprendre WordPress.

Actions vs Filtres : la différence clé

Actions : « Fais quelque chose à ce moment »

Une action est un point dans le code WordPress où vous pouvez insérer votre propre code. L’action ne retourne rien — elle exécute une tâche.

// "Quand WordPress charge le footer, ajoute mon script analytics"
function itsc_add_analytics() {
    ?>
    <!-- Mon code analytics ici -->
    <?php
}
add_action('wp_footer', 'itsc_add_analytics');

// "Quand un article est publié, envoie une notification"
function itsc_notify_on_publish($post_id, $post) {
    if ($post->post_type === 'post') {
        wp_mail('admin@monsite.com', 'Nouvel article', 'Article publié : ' . $post->post_title);
    }
}
add_action('publish_post', 'itsc_notify_on_publish', 10, 2);

Filtres : « Modifie cette valeur avant qu’elle soit utilisée »

Un filtre reçoit une valeur, la modifie (ou non), et la retourne. Il doit TOUJOURS retourner quelque chose.

// "Modifie le titre de l'article avant affichage"
function itsc_modify_title($title) {
    if (is_single()) {
        return $title . ' | ITSkillsCenter';
    }
    return $title; // TOUJOURS retourner la valeur
}
add_filter('the_title', 'itsc_modify_title');

// "Change la longueur de l'extrait"
function itsc_excerpt_length($length) {
    return 25; // 25 mots au lieu de 55
}
add_filter('excerpt_length', 'itsc_excerpt_length');

Résumé de la différence

Aspect Action Filtre
Fonction add_action() add_filter()
But Exécuter du code Modifier une valeur
Retour Rien (void) Obligatoire (la valeur modifiée)
Exemple Envoyer un email quand un post est créé Modifier le contenu d’un post

Syntaxe complète

add_action( string $hook, callable $callback, int $priority = 10, int $accepted_args = 1 );
add_filter( string $hook, callable $callback, int $priority = 10, int $accepted_args = 1 );

Priorité

La priorité détermine l’ordre d’exécution quand plusieurs fonctions sont accrochées au même hook :

  • 1 : Exécuté en premier
  • 10 : Priorité par défaut
  • 99 : Exécuté en dernier
// Cette fonction s'exécute APRÈS les autres
add_filter('the_content', 'itsc_add_cta_after_content', 99);

// Cette fonction s'exécute AVANT les autres
add_filter('the_content', 'itsc_modify_content_early', 1);

Nombre d’arguments

Par défaut, votre callback reçoit 1 argument. Si le hook en passe plus, indiquez-le :

// save_post passe 3 arguments : post_id, post object, update boolean
function itsc_on_save($post_id, $post, $update) {
    // $update est true si c'est une mise à jour, false si création
    if (!$update) {
        // Nouveau post créé
    }
}
add_action('save_post', 'itsc_on_save', 10, 3); // 3 arguments

Les hooks les plus utilisés

Actions essentielles

// Chargement des styles et scripts
add_action('wp_enqueue_scripts', function() {
    wp_enqueue_style('mon-style', get_stylesheet_uri());
    wp_enqueue_script('mon-script', get_template_directory_uri() . '/js/main.js', array(), '1.0', true);
});

// Configuration du thème (une seule fois)
add_action('after_setup_theme', function() {
    add_theme_support('post-thumbnails');
    add_theme_support('title-tag');
    register_nav_menus(array('primary' => 'Menu Principal'));
});

// Enregistrer les widgets
add_action('widgets_init', function() {
    register_sidebar(array('name' => 'Sidebar', 'id' => 'sidebar-1'));
});

// Enregistrer les Custom Post Types
add_action('init', function() {
    register_post_type('portfolio', array(/* ... */));
});

// Code dans le <head>
add_action('wp_head', function() {
    echo '<meta name="author" content="ITSkillsCenter">';
});

// Code avant </body>
add_action('wp_footer', function() {
    // Scripts analytics, widgets, etc.
});

// Quand un article est publié
add_action('publish_post', function($post_id) {
    // Notification, mise à jour de cache, etc.
});

// Quand un utilisateur s'inscrit
add_action('user_register', function($user_id) {
    // Email de bienvenue, ajout à une liste, etc.
});

// Scripts dans l'admin seulement
add_action('admin_enqueue_scripts', function($hook) {
    // $hook contient la page admin actuelle
    if ($hook === 'post.php') {
        wp_enqueue_script('mon-admin-script', '...');
    }
});

// Ajouter des colonnes dans la liste des articles
add_action('manage_posts_columns', function($columns) {
    $columns['views'] = 'Vues';
    return $columns;
});

Filtres essentiels

// Modifier le contenu de l'article
add_filter('the_content', function($content) {
    if (is_single() && in_the_loop()) {
        // Ajouter un CTA après le contenu
        $cta = '<div class="post-cta"><a href="/newsletter">Abonnez-vous</a></div>';
        $content .= $cta;
    }
    return $content;
});

// Modifier l'extrait
add_filter('excerpt_length', function() { return 30; });
add_filter('excerpt_more', function() { return '...'; });

// Modifier la requête principale
add_filter('pre_get_posts', function($query) {
    if (!is_admin() && $query->is_main_query()) {
        if ($query->is_home()) {
            $query->set('posts_per_page', 12);
        }
        if ($query->is_category()) {
            $query->set('orderby', 'title');
            $query->set('order', 'ASC');
        }
    }
});

// Ajouter des classes au body
add_filter('body_class', function($classes) {
    if (is_single()) {
        $classes[] = 'single-article';
    }
    return $classes;
});

// Modifier le texte "Lire la suite"
add_filter('the_content_more_link', function() {
    return '<a href="' . get_permalink() . '" class="read-more">Lire la suite →</a>';
});

// Personnaliser le formulaire de connexion
add_filter('login_headerurl', function() {
    return home_url('/');
});

// Modifier les paramètres de l'upload
add_filter('upload_mimes', function($mimes) {
    $mimes['svg'] = 'image/svg+xml';  // Autoriser les SVG
    $mimes['webp'] = 'image/webp';    // Autoriser les WebP
    return $mimes;
});

// Désactiver les emojis WordPress (performance)
add_filter('emoji_svg_url', '__return_false');
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('wp_print_styles', 'print_emoji_styles');

Créer vos propres hooks

Vous pouvez créer vos propres hooks dans vos thèmes et plugins pour les rendre extensibles :

Créer une action personnalisée

// Dans votre code, à l'endroit où vous voulez permettre l'extension
function itsc_process_order($order_id) {
    // Votre logique de commande...
    
    // Déclencher votre hook personnalisé
    do_action('itsc_order_completed', $order_id, $order_total);
    
    // D'autres développeurs peuvent s'y accrocher :
    // add_action('itsc_order_completed', 'ma_notification_sms', 10, 2);
}

Créer un filtre personnalisé

// Dans votre code
function itsc_format_price($price) {
    $formatted = number_format($price, 0, ',', ' ') . ' FCFA';
    
    // Permettre la modification du format
    return apply_filters('itsc_price_format', $formatted, $price);
}

// Un autre développeur peut modifier le format :
add_filter('itsc_price_format', function($formatted, $price) {
    return $price . ' XOF'; // Format différent
}, 10, 2);

Supprimer des hooks

Vous pouvez retirer un hook ajouté par WordPress, un thème ou un plugin :

// Supprimer une action
remove_action('wp_head', 'wp_generator'); // Retire la version WordPress du <head>
remove_action('wp_head', 'wlwmanifest_link'); // Retire le lien WLW
remove_action('wp_head', 'rsd_link'); // Retire le lien RSD
remove_action('wp_head', 'wp_shortlink_wp_head'); // Retire le shortlink

// Supprimer un filtre
remove_filter('the_content', 'wpautop'); // Retire les <p> automatiques

// Important : la priorité doit être la même que lors de l'ajout
// Si le hook a été ajouté avec priorité 15 :
remove_action('wp_head', 'ma_fonction', 15);

Déboguer les hooks

Voir tous les hooks actifs

// Ajouter temporairement dans functions.php
function itsc_debug_hooks() {
    global $wp_filter;
    
    // Voir tous les filtres sur 'the_content'
    if (isset($wp_filter['the_content'])) {
        echo '<pre>';
        print_r($wp_filter['the_content']);
        echo '</pre>';
    }
}
add_action('wp_footer', 'itsc_debug_hooks');

Plugin : Query Monitor

Installez Query Monitor (gratuit) — il affiche tous les hooks déclenchés sur chaque page, avec le temps d’exécution de chaque callback. C’est l’outil de debug WordPress le plus utile.

Bonnes pratiques pour les hooks

1. Toujours préfixer vos fonctions

// MAUVAIS : risque de conflit
function send_email() { }
add_action('publish_post', 'send_email');

// BON : préfixe unique
function itsc_send_email_on_publish() { }
add_action('publish_post', 'itsc_send_email_on_publish');

2. Toujours retourner dans les filtres

// MAUVAIS : casse tout le contenu du site
add_filter('the_content', function($content) {
    if (is_single()) {
        $content .= '<p>Merci d'avoir lu !</p>';
    }
    // Oubli de return = le contenu disparaît partout
});

// BON : retour dans tous les cas
add_filter('the_content', function($content) {
    if (is_single()) {
        $content .= '<p>Merci d'avoir lu !</p>';
    }
    return $content; // TOUJOURS retourner
});

3. Vérifier le contexte

// MAUVAIS : modifie le titre PARTOUT (admin, menus, widgets...)
add_filter('the_title', function($title) {
    return $title . ' — MonSite';
});

// BON : seulement dans le contenu principal
add_filter('the_title', function($title, $post_id) {
    if (is_single() && in_the_loop() && is_main_query()) {
        return $title . ' — MonSite';
    }
    return $title;
}, 10, 2);

4. Utiliser les conditional tags

is_single()      // Article individuel
is_page()        // Page
is_home()        // Page d'accueil du blog
is_front_page()  // Page d'accueil (statique ou blog)
is_archive()     // Page d'archive (catégorie, tag, date)
is_category()    // Page de catégorie
is_search()      // Page de résultats de recherche
is_admin()       // Dashboard admin
is_user_logged_in()  // Utilisateur connecté
in_the_loop()    // Dans la boucle WordPress
is_main_query()  // Requête principale (pas une requête secondaire)

Hooks utiles par cas d’usage

SEO et performance

// Retirer les éléments inutiles du <head>
remove_action('wp_head', 'wp_generator');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wp_shortlink_wp_head');
remove_action('wp_head', 'rest_output_link_wp_head');

// Désactiver les commentaires sur les pages
add_filter('comments_open', function($open, $post_id) {
    if (get_post_type($post_id) === 'page') return false;
    return $open;
}, 10, 2);

WooCommerce

// Ajouter un texte sous le prix
add_action('woocommerce_after_shop_loop_item_title', function() {
    echo '<p class="livraison-info">Livraison Dakar : 2 000 FCFA</p>';
}, 15);

// Modifier le bouton "Ajouter au panier"
add_filter('woocommerce_product_single_add_to_cart_text', function() {
    return 'Commander maintenant';
});

// Rediriger après ajout au panier
add_filter('woocommerce_add_to_cart_redirect', function() {
    return wc_get_checkout_url(); // Direct au checkout
});

Sécurité

// Limiter les tentatives de connexion
add_filter('authenticate', function($user, $username, $password) {
    $ip = $_SERVER['REMOTE_ADDR'];
    $attempts = get_transient('login_attempts_' . $ip);
    
    if ($attempts >= 5) {
        return new WP_Error('too_many_attempts', 'Trop de tentatives. Réessayez dans 15 minutes.');
    }
    
    return $user;
}, 30, 3);

add_action('wp_login_failed', function() {
    $ip = $_SERVER['REMOTE_ADDR'];
    $attempts = (int) get_transient('login_attempts_' . $ip);
    set_transient('login_attempts_' . $ip, $attempts + 1, 15 * MINUTE_IN_SECONDS);
});
#actions #filtres #hooks
Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 350.000 FCFA
Parlons de Votre Projet
Publicité

Articles Similaires