# Cibler pre_get_posts sur le front sans jamais perturber l’administration

> Comment modifier la requête principale avec pre_get_posts en visant précisément le front, sans jamais casser un écran ou un widget d'administration.

- Auteur : WordPress Développement
- Publié le : 2020-02-13
- Mis à jour le : 2020-02-13
- Catégorie : Extensions
- URL : https://www.wpmoderne.fr/extensions/pre-get-posts-modifier-requete-sans-casser-admin/

## L’essentiel

- Vérifier is_admin() ET is_main_query()
- Ne jamais toucher aux requêtes secondaires
- Tester sur une recherche et une archive

Comment savoir, à l'intérieur d'un callback accroché à `pre_get_posts`, si l'on est en train de modifier la bonne requête et pas une autre ? La question revient sans cesse chez les développeurs qui découvrent ce hook : il se déclenche pour absolument toutes les instances de `WP_Query`, y compris celles qui affichent un widget « articles récents » dans la colonne latérale de l'administration ou celles générées par une extension tierce sur le front.

Sans garde-fou, une modification pensée pour la page d'accueil du site peut très bien s'appliquer à la liste des articles dans l'écran d'édition, avec des résultats déroutants : des contenus manquants, un tri différent, ou pire, un filtre par type de contenu qui masque des brouillons à un auteur qui cherche les siens.

## Deux conditions à poser systématiquement

La combinaison qui protège de la quasi-totalité des effets de bord tient en deux vérifications, à placer en tout début de callback :

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

    if ( $query->is_home() ) {
        $query->set( 'posts_per_page', 12 );
        $query->set( 'meta_key', 'wpm_mis_en_avant' );
        $query->set( 'orderby', 'meta_value_num date' );
        $query->set( 'order', 'DESC' );
    }
}
add_action( 'pre_get_posts', 'wpm_filtrer_articles_recents' );
```

`is_admin()` écarte tout ce qui se passe derrière l'écran d'administration, mais elle ne suffit pas seule : une extension peut très bien lancer une `WP_Query` secondaire sur le front, par exemple pour afficher des articles liés en pied de page. C'est là qu'intervient `is_main_query()`, qui ne renvoie `true` que pour la requête principale déclenchée par WordPress pour construire la page demandée par l'URL.

## Cibler le bon type de page avant de toucher aux paramètres

Une fois ces deux conditions posées, il reste à choisir avec précision quelle page est concernée. Les méthodes conditionnelles de `WP_Query` couvrent la plupart des cas : `is_home()` pour la page d'accueil des articles, `is_search()` pour les résultats de recherche, `is_post_type_archive()` pour une archive de type personnalisé, `is_tax()` pour une taxonomie.

> L'essentiel à retenir : Vérifier is_admin() ET is_main_query() ; Ne jamais toucher aux requêtes secondaires ; Tester sur une recherche et une archive

Une erreur fréquente consiste à tester `is_home()` seule alors que la page d'accueil du site a été configurée pour afficher une page statique. Dans ce cas, `is_home()` reste vraie pour la page qui liste les articles, mais ce n'est peut-être pas celle que le développeur croit viser. Un test rapide avec `var_dump( $query->query_vars )` derrière un `if ( WP_DEBUG )` permet de lever le doute avant de livrer.

### Adapter une recherche sans exclure de contenus utiles

Sur une recherche, il est tentant de restreindre les types de contenus interrogés avec `set( 'post_type', ... )`. C'est légitime pour exclure des types techniques (des modèles internes, par exemple), mais il faut résister à l'envie de restreindre trop large : un visiteur qui cherche un mot précis s'attend à retrouver aussi bien un article qu'une page si elle contient ce mot.

- Toujours partir de `$query->get( 'post_type' )` pour ne pas écraser une valeur déjà définie ailleurs
- Combiner avec `tax_query` plutôt que de dupliquer la requête dans le thème
- Documenter dans un commentaire pourquoi telle condition a été choisie, pour la personne qui reprendra le code

## Vérifier les widgets et les requêtes secondaires du thème

Le piège le plus sournois n'est pas l'administration, déjà écartée par `is_admin()`, mais les requêtes secondaires lancées par le thème actif lui-même : un widget « articles à la une », une boucle de suggestions en pied d'article, un carrousel en page d'accueil. Chacune de ces boucles instancie sa propre `WP_Query`, et `is_main_query()` les exclut correctement du filtre pensé pour la requête principale.

Si l'objectif est justement de modifier l'une de ces requêtes secondaires, la bonne pratique consiste à passer un identifiant personnalisé dans les arguments de la requête, puis à le vérifier dans le callback plutôt que de retirer le test `is_main_query()` :

```
$args = array(
    'post_type'   => 'produit',
    'wpm_widget'  => 'suggestions',
);
$requete = new WP_Query( $args );
```

```
function wpm_filtrer_widget_suggestions( $query ) {
    if ( 'suggestions' !== $query->get( 'wpm_widget' ) ) {
        return;
    }
    $query->set( 'posts_per_page', 4 );
}
add_action( 'pre_get_posts', 'wpm_filtrer_widget_suggestions' );
```

## Tester avant de livrer

Un plan de test minimal couvre quatre scénarios : la page d'accueil, une recherche avec un terme courant, une archive de type personnalisé et, surtout, l'écran « Tous les articles » de l'administration avec un compte auteur. Ce dernier test révèle immédiatement une éventuelle fuite du filtre côté back-office.

| Scénario | Résultat attendu | Piège fréquent |
| --- | --- | --- |
| Page d'accueil | Tri personnalisé appliqué | Confusion avec une page statique |
| Recherche | Types de contenus élargis | Exclusion trop stricte des pages |
| Écran admin | Aucun changement | Oubli de is_admin() |
| Widget du thème | Non affecté par erreur | Oubli de is_main_query() |

> Sur nos projets, la règle interne est simple : aucun callback accroché à `pre_get_posts` n'est validé en revue de code sans les deux conditions de garde en première ligne.

## En résumé

`pre_get_posts` reste l'un des hooks les plus puissants pour ajuster une requête sans dupliquer de code de boucle dans un thème, à condition de ne jamais oublier que ce hook parle à toutes les requêtes du site, sans distinction. Deux lignes de garde, un ciblage précis des pages concernées et un test systématique sur l'écran d'administration suffisent à éviter la quasi-totalité des régressions observées sur ce type de code.
