Skip to main content

Fonctionnement

Le Hook pre_get_posts

Le hook pre_get_posts s'applique aux requêtes principales effectuées par WordPress, nottament pour les recherches, les pages d'archive, et la page d'accueil. En se branchant sur ce hook, vous pouvez modifier les paramètres de ces requêtes juste avant qu'elles ne soient exécutées. Cela vous permet de personnaliser les résultats sans requêtes supplémentaires, ce qui peut améliorer les performances de votre site.

Voici un exemple de base de l'utilisation de pre_get_posts :

/inc/popcorn/recherche.php
add_action( 'pre_get_posts', 'custom_modify_query' );
function custom_modify_query( $query ) {
if ( !is_admin() && $query->is_main_query() ) {
if ( $query->is_search() ) {
// Modifier la requête de recherche ici
}
}
}

Dans cet exemple, nous vérifions d'abord si nous sommes sur une requête principale et non dans l'administration de WordPress. Ensuite, si la requête est une recherche ($query->is_search()), nous procédons aux modifications souhaitées.

Fonction custom_modify_query()

La fonction custom_modify_query() contient notre code personnalisé permetant d'ajuster les paramètres de la requête de recherche. Nous initialisons les parametres classique d'une recherche Wordpress, puis y ajustons des spécificités de recherche sous certains conditions.

Voici comment cela fonctionne :

1. Initialisation de la requete

Tout d'abord, nous initialisation la recherche personnalisée.

/inc/popcorn/recherche.php
// Désactivez la recherche native en définissant la requête sur un post inexistant
$query->set( 'post__in', array(0) );

// Init arguments query
$paged = get_query_var('page') ?: 1;
$nb_post = get_option('posts_per_page') ?: 15;
$args = array(
'post_type' => 'post',
// 'post_status' => array('publish', 'draft'),
'post_status' => array('publish'),
'posts_per_page' => $nb_post,
'paged' => $paged,
'meta_key' => 'n_de_dossier',
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_query' => array( 'relation' => 'AND' ),
);

2. Personnalisation de la recherche

Ensuite, nous ajoutons des personnalisations de la recherche (ordre de tri, fond recherché, type de document...) :

/inc/popcorn/recherche.php
// Ordre de TRI
if( !empty( $_GET['trier-par'] ) ){
if( $_GET['trier-par'] == 'date'){
$args['orderby'] = 'post_date';
$args['order'] = 'DESC';
}
else if( $_GET['trier-par'] == 'titre'){
$args['orderby'] = 'title';
$args['order'] = 'ASC';
}
else if( $_GET['trier-par'] == 'pertinence' || $_GET['trier-par'] == 'dossier' ){
// $args['orderby'] = 'relevance';
// // unset( $args['orderby'] );
// unset( $args['order'] );
$args['meta_key'] = 'n_de_dossier';
$args['orderby'] = 'meta_value';
$args['order'] = 'ASC';
}
else if( $_GET['trier-par'] == 'type'){
$args['meta_key'] = 'type_de_document';
$args['orderby'] = 'meta_value';
$args['order'] = 'ASC';
}
}

// Fond 39-45 uniquement
if( !empty( $_GET['fonds-39-45'] ) ){
$args['meta_query'][] = array(
'key' => 'transparence_3945',
'value' => 1,
'compare' => '=',
);
}

// Type de document
if (isset($_GET['type']) && is_array($_GET['type'])) {
// Relation
$search_types = ['relation' => 'OR'];
// Liste des types de docs
foreach ($_GET['type'] as $value) {
$search_types[] = array(
'key' => 'type_de_document',
'value' => $value,
'compare' => 'LIKE',
);
}
// Add to query
$args['meta_query'][] = $search_types;
}

3. Gestion des dates

Ce code filtre les posts basés sur des dates de début et de fin spécifiées par l'utilisateur via les paramètres date-debut et date-fin dans l'URL (en provenance du formulaire de recherche). Il construit une requête complexe qui recherche les posts dont les dates s'inscrivent dans l'intervalle spécifié, en considérant les cas où la date de début ou de fin du post correspond ou dépasse les critères de recherche.

/inc/popcorn/recherche.php
if( !empty($_GET['date-debut']) || !empty($_GET['date-fin']) ){
// Relation
$search_dates = ['relation' => 'AND'];
// Debut (qui ont une date de début ou de fin supérieure à la date de début recherchée (prevent one missing value) )
if( isset($_GET['date-debut']) && !empty($_GET['date-debut']) ){
$search_dates[] = [
'relation' => 'OR',
[
'key' => 'debut',
'value' => $_GET['date-debut'],
'compare' => '>=',
'type' => 'NUMERIC',
],
[
'key' => 'fin',
'value' => $_GET['date-debut'],
'compare' => '>=',
'type' => 'NUMERIC',
],
];
}
// Fin (qui ont une date de début ou de fin supérieure à la date de début recherchée (prevent one missing value) )
if( isset($_GET['date-fin']) && !empty($_GET['date-fin']) ){
$search_dates[] = [
'relation' => 'OR',
[
'key' => 'debut',
'value' => array('1900', $_GET['date-fin']),
'compare' => 'BETWEEN',
'type' => 'NUMERIC',
],
[
'key' => 'fin',
'value' => array('1900', $_GET['date-fin']),
'compare' => 'BETWEEN',
'type' => 'NUMERIC',
],
];
}
// Add to query
$args['meta_query'][] = $search_dates;
}

La logique se décompose comme suit :

  • Vérification des Paramètres : Le script commence par vérifier si au moins l'un des paramètres de date est fourni.
  • Construction de la Requête : Une requête meta_query est construite avec des conditions qui incluent les posts si leur date de début ou de fin est dans l'intervalle défini par les paramètres date-debut et date-fin.
    • Pour date-debut, il recherche les posts dont la date de début ou de fin est supérieure ou égale à la date de début fournie.
    • Pour date-fin, il inclut les posts dont la date de début ou de fin est dans l'intervalle entre 1900 et la date de fin spécifiée.
  • Application de la Requête : Cette condition de filtrage est ensuite ajoutée à la requête principale pour affecter les résultats de recherche.

En bref, ce script permet de filtrer les posts dans une plage de dates définie par l'utilisateur, en adaptant les résultats de recherche pour inclure uniquement ceux qui correspondent aux critères de dates spécifiés.

4. Gestion des termes de recherche

Ce code analyse les termes de recherche fournis par l'utilisateur via l'URL et ajuste la requête WordPress en conséquence, utilisant trois types de comparaison : égal à (egal), ne contient pas (ne-contient-pas), et contient (contient). Pour chaque terme de recherche (terme-1 à terme-5), il vérifie le type de comparaison spécifié (type-terme-i) et applique les conditions appropriées à la requête.

Il peut y avoir jusqu'a 5 termes combinés par l'utilisateur.

tip

Comme spécifié, nous recherchons donc sur le champ data_pour_recherche, qui contient différent sous-champs ACF concaténés.

/inc/popcorn/recherche.php
// Parcours des wordings (termes de recherche)
for( $i=1; $i <= 5; $i++) {
if( isset($_GET['terme-'.$i]) && !empty($_GET['terme-'.$i]) && isset($_GET['type-terme-'.$i]) ){

// 1 - Strictement égal à -----------------------------------------------------
if( 'egal' == $_GET['type-terme-'.$i] ){
// values query
$comparateur = 'LIKE';
$search_terme = ['relation' => 'OR'];
$value = $_GET['terme-'.$i];
$value = '--- ' . $value . ' ---';
// term search
$search_terme[] = array(
'key' => 'data_pour_recherche', // Recherche sur un unique field (pour limiter les ressources msql) concatainant plusieurs sous-champs acf : titre - themes - motcles --- n_de_boite - n_de_dossier
'value' => $value,
'compare' => $comparateur,
);
$search_terme[] = array(
'key' => 'resume_pour_diffusion',
'value' => $value,
'compare' => $comparateur,
);
// Add to query
$args['meta_query'][] = $search_terme;
}

// 2 - Ne contient pas --------------------------------------------------------
else if( 'ne-contient-pas' == $_GET['type-terme-'.$i] ){
// values query
$comparateur = 'NOT LIKE';
$value = $_GET['terme-'.$i];
$search_terme = ['relation' => 'AND'];
// term search
$search_terme[] = array(
'key' => 'data_pour_recherche', // Recherche sur un unique field (pour limiter les ressources msql) concatainant plusieurs sous-champs acf : titre - themes - motcles --- n_de_boite - n_de_dossier
'value' => $value,
'compare' => $comparateur,
);
$search_terme[] = array(
'key' => 'resume_pour_diffusion',
'value' => $value,
'compare' => $comparateur,
);
// Add to query
$args['meta_query'][] = $search_terme;
}

// 3 - Contient ----------------------------------------------------------------
else if( 'contient' == $_GET['type-terme-'.$i] ){
// init string / words
$value = $_GET['terme-'.$i];
$words = search_string_to_words( $value );
// terms search
foreach( $words as $value ){
// values query
$comparateur = 'LIKE';
$search_terme = ['relation' => 'OR'];
// term search
$search_terme[] = array(
'key' => 'data_pour_recherche', // Recherche sur un unique field (pour limiter les ressources msql) concatainant plusieurs sous-champs acf : titre - themes - motcles --- n_de_boite - n_de_dossier
'value' => $value,
'compare' => $comparateur,
);
$search_terme[] = array(
'key' => 'resume_pour_diffusion',
'value' => $value,
'compare' => $comparateur,
);
// Add to query
$args['meta_query'][] = $search_terme;
}
}

}
}
  1. Égal à (egal)
    Pour une recherche stricte, il ajoute des conditions pour chercher des posts dont l'un des champs correspond exactement au terme spécifié, soit dans le champ data_pour_recherche soit dans resume_pour_diffusion (qui reste traité séparément pour le moment). La recherche utilise l'opérateur LIKE pour inclure les posts contenant le terme encadré de marqueurs (--- terme ---).
  2. Ne contient pas (ne-contient-pas)
    Inversement, pour exclure des posts contenant un terme spécifique, il utilise l'opérateur NOT LIKE. Deux champs sont examinés pour chaque terme : data_pour_recherche et resume_pour_diffusion, excluant les posts qui mentionnent le terme. Cela crée une condition où les posts doivent répondre à toutes les exigences de non-inclusion pour être sélectionnés.
  3. Contient (contient)
    La recherche par défaut. Pour une recherche souple, il décompose le terme de recherche en mots individuels et cherche des posts qui contiennent au moins un de ces mots dans les champs spécifiés. Cela est réalisé en utilisant l'opérateur LIKE pour chaque mot du terme de recherche, appliquant une condition d'inclusion souple.
info

La fonction search_string_to_words() est définie dans le même fichier. Elle permet de traiter les mots contenu dans les champs "termes de recherche", en retirant le pluriel de certains mots, en appliquant des corections via un tableau de correspondances des fautes fréquentes...