# Ajouter un filtre par plage de dates personnalisée à la liste des articles

> Deux sélecteurs de date, une requête ajustée : voici comment compléter l'écran des articles pour retrouver un contenu publié entre deux dates précises.

- Auteur : Clément Hadrot
- Publié le : 2021-01-16
- Mis à jour le : 2021-01-16
- Catégorie : Tips
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tips/filtre-plage-dates-personnalisee-liste-articles/

## L’essentiel

- Deux champs de saisie ajoutés au-dessus du tableau
- La requête est corrigée via pre_get_posts
- Fonctionne aussi bien pour les articles que pour un CPT

Une rédactrice en chef nous a expliqué son problème avec une précision presque comique : « Je cherche tous les articles publiés entre le 15 mars et le 2 avril, mais WordPress ne me propose que des mois entiers dans son menu déroulant. » Elle avait raison : le filtre natif par date, dans l'écran des articles, ne descend pas en dessous du mois. Pour une recherche par plage précise, il fallait construire quelque chose sur mesure.

La solution tient en deux morceaux : un formulaire HTML simple, injecté au-dessus du tableau des articles via `restrict_manage_posts`, et une correction de la requête SQL sous-jacente via `pre_get_posts`. Voici comment les assembler pas à pas.

## Étape 1 : afficher les deux champs de date

Le hook `restrict_manage_posts` s'exécute juste avant le bouton « Filtrer », dans la barre d'outils au-dessus de la liste. Il reçoit le type de contenu courant, ce qui permet de limiter l'affichage aux seuls articles :

```
function rd_afficher_filtre_dates( $post_type ) {
    if ( 'post' !== $post_type ) {
        return;
    }

    $date_debut = isset( $_GET['rd_date_debut'] ) ? sanitize_text_field( $_GET['rd_date_debut'] ) : '';
    $date_fin   = isset( $_GET['rd_date_fin'] ) ? sanitize_text_field( $_GET['rd_date_fin'] ) : '';
    ?>
    <input type="date" name="rd_date_debut" value="<?php echo esc_attr( $date_debut ); ?>" style="margin-right:4px;" />
    <input type="date" name="rd_date_fin" value="<?php echo esc_attr( $date_fin ); ?>" />
    <?php
}
add_action( 'restrict_manage_posts', 'rd_afficher_filtre_dates' );
```

## Étape 2 : corriger la requête principale

> L'essentiel à retenir : Deux champs de saisie ajoutés au-dessus du tableau ; La requête est corrigée via pre_get_posts ; Fonctionne aussi bien pour les articles que pour un CPT

Le hook `pre_get_posts` intercepte la requête avant son exécution. Il faut impérativement vérifier qu'on se trouve bien sur l'écran d'administration concerné, sur la requête principale, et pour le bon type de contenu, sous peine de casser d'autres requêtes du site :

```
function rd_appliquer_filtre_dates( $query ) {
    if ( ! is_admin() || ! $query->is_main_query() ) {
        return;
    }

    global $pagenow;
    if ( 'edit.php' !== $pagenow || 'post' !== $query->get( 'post_type' ) ) {
        return;
    }

    $date_debut = isset( $_GET['rd_date_debut'] ) ? sanitize_text_field( $_GET['rd_date_debut'] ) : '';
    $date_fin   = isset( $_GET['rd_date_fin'] ) ? sanitize_text_field( $_GET['rd_date_fin'] ) : '';

    if ( empty( $date_debut ) && empty( $date_fin ) ) {
        return;
    }

    $query->set( 'date_query', array(
        array(
            'after'     => $date_debut ? $date_debut : '1970-01-01',
            'before'    => $date_fin ? $date_fin . ' 23:59:59' : current_time( 'mysql' ),
            'inclusive' => true,
        ),
    ) );
}
add_action( 'pre_get_posts', 'rd_appliquer_filtre_dates' );
```

L'argument `date_query` repose sur la classe interne `WP_Date_Query`, la même qui alimente les filtres natifs par mois. Utiliser cette classe plutôt qu'une clause SQL manuelle garantit une compatibilité totale avec les fuseaux horaires configurés sur le site.

## Ne pas casser le bouton « Filtrer » natif

Une erreur fréquente consiste à oublier que le formulaire de filtre, une fois soumis, conserve tous les paramètres `$_GET` existants, y compris ceux du filtre par catégorie ou par auteur déjà présents sur l'écran. Comme `restrict_manage_posts` s'exécute à l'intérieur du même formulaire que les filtres natifs, il n'y a rien de spécial à faire : les champs ajoutés sont automatiquement transmis avec le reste.

## Adapter à un type de contenu personnalisé

Pour appliquer ce filtre à un CPT nommé `evenement` plutôt qu'aux articles, il suffit d'ajuster les deux conditions de type de contenu dans les fonctions ci-dessus. Le reste de la logique, formulaire et requête, reste identique. Ce filtre par plage ne remplace pas un filtre par taxonomie personnalisée, déjà couvert par ailleurs sur ce même écran ; les deux peuvent d'ailleurs cohabiter sans conflit, puisqu'ils agissent sur des paramètres `$_GET` distincts.

## Limiter l'impact sur les performances

- Le filtre par date s'appuie sur l'index de la colonne `post_date`, déjà présent nativement, donc aucune requête coûteuse supplémentaire.
- Éviter de combiner ce filtre avec un tri par méta-donnée non indexée : la combinaison des deux ralentit sensiblement les grandes tables d'articles.
- Sur un site avec plusieurs dizaines de milliers d'articles, envisager de limiter la plage maximale acceptée pour éviter des requêtes portant sur des années entières.

## En résumé

Un formulaire minimal et une correction de requête via `pre_get_posts` suffisent à combler un manque réel de l'écran d'administration natif. Cette approche reste légère, ne dépend d'aucune extension tierce, et s'adapte à n'importe quel type de contenu en quelques minutes.
