Créer une requête Eloquent avec une clause orWhere et LIKE sur une boucle (for ou foreach) ?

Imaginons que nous voulions ajouter un module de recherche sur notre site Laravel (rien d’extravagant vous me direz), ça serait surement intéressant de faire une recherche sur plusieurs mots par exemple.

Pour réaliser ça, on va mettre les mots contenus dans la recherche dans un tableau :

$title_words = explode(' ', $request->input('title_part'));

Puis on va construire notre requête Eloquent avec une fonction qui prendra la requête (query) en utilisant notre tableau de mots et qui ajoutera la clause orwhere / LIKE pour chaque mot :

Post::select('*') 
->Where(function ($query) use($title_words) { 
    for ($i = 0; $i < count($title_words); $i++){ 
        $query->orwhere('title', 'LIKE', '%'.$title_words[$i] .'%'); 
    } 
}) 
->get();

Et voici la fonction en entier :

Aller plus loin : On pourra améliorer la fonction en retirant les mots non pertinents comme : car, il, où, comment, combien etc… avant de transformer la chaine de recherche en tableau (Attention éventuellement à l’encodage des accents).

La fonction de suppression est mots inutiles pourrait être comme ça :

private function remove_not_usefull_words($str){
    // to lower case
    $str = strtolower($str);

    // exclude words (rajouter ceux qui manquent)
    $not_use_words = ['comment', 'que', 'qui', 'quand', 'pourquoi', 'pour', 'quoi', 
                      'comme', 'avec', 'sans', 'faire', 'avoir', 'être', 'mais',
                      'ou', 'et', 'donc', 'or', 'ni', 'car', 'si', 'de', 'des',
                      'un', 'une', 'juste', 'qu', 'est', 'sont', 'lors', 'en', 'a'];

    $len = count($not_use_words);
    // remove words
    for ($i=0; $i < $len; $i++) {
        $str = str_replace($not_use_words[$i].' ', '', $str);
    }

    return $str;
}

Et donc la nouvelle fonction de recherche serait alors :

public function search(Request $request){
    $title_part = $this->remove_not_usefull_words($request->input('title_part'));
    $title_words = explode(' ', $title_part);
    $posts = Post::select('*')
             ->Where(function ($query) use($title_words) {
                 for ($i = 0; $i < count($title_words); $i++){
                     $query->orwhere('title', 'LIKE', '%'.$title_words[$i] .'%');
                 }
             })
             ->get();

    return view('posts.results', compact('posts'));
}

Aller, je vous laisse customiser vos requêtes tranquille !

Laisser un commentaire