vendredi 25 septembre 2026

À propos

Contact

Extensions

WP-Cron dans les extensions : les pièges classiques et comment les éviter

WP-Cron ne s'exécute que sur une visite, dérive dans le temps et duplique facilement ses tâches : tour des erreurs les plus fréquentes et de leurs corrections.

Par Clément Hadrot • 21 septembre 2021 • 5 min de lecture • Aucun commentaire
WP-Cron dans les extensions : les pièges classiques et comment les éviter

WP-Cron porte mal son nom : ce n’est pas un vrai cron système, mais un mécanisme déclenché à chaque visite du site via une requête vers wp-cron.php, qui vérifie si des tâches planifiées sont arrivées à échéance. Ce choix de conception, pensé pour fonctionner même sur un hébergement mutualisé sans accès à la crontab du serveur, explique à lui seul l’essentiel des problèmes rencontrés en production.

Cet article recense les pièges les plus fréquents observés dans des extensions qui utilisent wp_schedule_event(), avec pour chacun la correction concrète à appliquer.

Piège n°1 : programmer une tâche à chaque chargement

L’erreur la plus commune consiste à appeler wp_schedule_event() directement dans le corps du fichier principal de l’extension, sans vérification préalable :

// À NE PAS FAIRE : reprogramme la tâche à chaque requête
add_action( 'init', function () {
    wp_schedule_event( time(), 'hourly', 'acme_verification_stock' );
} );

wp_schedule_event() ne vérifie pas par lui-même si une tâche identique existe déjà exactement de cette façon ; répéter cet appel finit par empiler des dizaines d’événements identiques dans la table d’options cron, ralentissant chaque vérification de WP-Cron. La correction :

register_activation_hook( __FILE__, function () {
    if ( ! wp_next_scheduled( 'acme_verification_stock' ) ) {
        wp_schedule_event( time(), 'hourly', 'acme_verification_stock' );
    }
} );

register_deactivation_hook( __FILE__, function () {
    $timestamp = wp_next_scheduled( 'acme_verification_stock' );
    if ( $timestamp ) {
        wp_unschedule_event( $timestamp, 'acme_verification_stock' );
    }
} );

La programmation a lieu une seule fois, à l’activation, et la tâche est proprement retirée à la désactivation. C’est la seule approche fiable pour éviter l’accumulation d’événements fantômes.

Piège n°2 : croire à une précision horaire

Sans visite sur le site, wp-cron.php n’est jamais déclenché. Un site à faible trafic peut voir une tâche programmée « toutes les heures » ne s’exécuter en réalité qu’une fois par jour, au moment de la première visite. C’est un problème réel pour toute logique métier sensible au temps : purge de sessions expirées, envoi d’e-mails programmés, synchronisation avec un service externe.

Sur un projet e-commerce à trafic modéré, une tâche de relance panier programmée « toutes les heures » ne se déclenchait en pratique qu’entre deux et quatre fois par jour. Le diagnostic a pris du temps car WP-Cron ne signale jamais explicitement qu’il n’a pas pu s’exécuter : il se contente de ne rien faire.

La solution recommandée en production consiste à désactiver le déclenchement par visite et à le remplacer par un vrai cron système, plus prévisible :

// Dans wp-config.php
define( 'DISABLE_WP_CRON', true );
# Dans la crontab du serveur, toutes les cinq minutes
*/5 * * * * curl -s https://exemple.fr/wp-cron.php?doing_wp_cron >/dev/null 2>&1

Attention : DISABLE_WP_CRON à true sans configuration d’un vrai cron système équivaut à désactiver purement et simplement toutes les tâches planifiées du site, y compris celles du cœur de WordPress (vérification des mises à jour, purge de la corbeille). C’est une erreur de configuration fréquente lors d’une migration d’hébergement.

L'essentiel à retenir : WP-Cron dépend du trafic, pas d'une horloge système ; Toujours vérifier wp_next_scheduled avant de programmer ; DISABLE_WP_CRON exige un vrai cron serveur en remplacement

Piège n°3 : des intervalles personnalisés mal déclarés

WordPress propose nativement hourly, twicedaily et daily. Un intervalle personnalisé doit être ajouté via le filtre cron_schedules, avant que wp_schedule_event() ne soit appelé, sous peine d’une erreur silencieuse qui empêche la programmation.

add_filter( 'cron_schedules', function ( $schedules ) {
    $schedules['acme_toutes_les_15_minutes'] = [
        'interval' => 15 * MINUTE_IN_SECONDS,
        'display'  => __( 'Toutes les 15 minutes', 'acme' ),
    ];
    return $schedules;
} );

La constante MINUTE_IN_SECONDS, ainsi que HOUR_IN_SECONDS, DAY_IN_SECONDS et WEEK_IN_SECONDS, sont définies nativement par WordPress et évitent d’écrire des calculs de secondes à la main, source classique d’erreur d’un facteur dix.

Piège n°4 : un callback trop long qui dépasse le temps d’exécution

Une tâche accrochée à un hook de cron s’exécute dans le même processus PHP que la requête qui a déclenché wp-cron.php, avec les mêmes limites de max_execution_time que n’importe quelle page. Un traitement lourd (synchronisation de plusieurs milliers de produits, par exemple) peut être interrompu brutalement avant la fin, sans transaction ni retour en arrière automatique.

  • Découper le traitement en lots (batches) traités sur plusieurs exécutions successives plutôt qu’en une seule passe
  • Enregistrer une progression en base (via une option ou une métadonnée) pour reprendre là où le traitement s’est arrêté
  • Pour des volumes importants ou des tâches déclenchées par événement plutôt que par intervalle fixe, envisager Action Scheduler plutôt que WP-Cron natif

Diagnostiquer les tâches programmées

WP-CLI reste l’outil le plus rapide pour inspecter l’état réel du cron d’un site, sans dépendre du trafic pour forcer une exécution :

wp cron event list
wp cron event run acme_verification_stock
wp cron test

La commande wp cron event run exécute immédiatement une tâche donnée, indépendamment de son échéance programmée : un outil précieux pour tester une tâche en développement sans attendre l’heure prévue.

En résumé

WP-Cron rend un vrai service sur les hébergements sans accès à la crontab, mais son fonctionnement dépendant du trafic le rend inadapté à toute tâche exigeant une précision horaire. Sur un projet en production sérieux, la combinaison DISABLE_WP_CRON plus un vrai cron système reste la configuration la plus fiable, à condition de ne jamais oublier de la mettre en place après une migration.

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