# 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.

- Auteur : Clément Hadrot
- Publié le : 2021-09-21
- Mis à jour le : 2021-09-21
- Catégorie : Extensions
- URL : https://wpmoderne.dev.wordpress-developpement.fr/extensions/wp-cron-pieges-classiques/

## L’essentiel

- 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

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.
