7

I am trying to create a way for users to search through all the products on a website. When they search for "burton snowboards", I only want the snowboards with the brand burton to appear in the results. But if they searched only "burton", then all products with the brand burton should appear.

This is what I have attempted to write but isn't working for multiple reasons.

Controller:

 public function search(){
    $input = Input::all();

    $v= Validator::make($input, Product::$rules);

    if($v->passes())
    {

        $searchTerms = explode(' ', $input);
        $searchTermBits = array();
        foreach ($searchTerms as $term) {
            $term = trim($term);
            if (!empty($term)){
                $searchTermBits[] = "search LIKE '%$term%'";
            }
        }
        $result = DB::table('products')
        ->select('*')
        ->whereRaw(". implode(' AND ', $searchTermBits) . ")
        ->get();

        return View::make('layouts/search', compact('result')); 
    }
    return Redirect::route('/');    
}

I am trying to recreate the first solution given for this stackoverflow.com problem

The first problem I have identified is that i'm trying to explode the $input, but it's already an array. So i'm not sure how to go about fixing that. And the way I have written the ->whereRaw(". implode(' AND ', $searchTermBits) . "), i'm sure isn't correct. I'm not sure how to fix these problems though, any insights or solutions will be greatly appreciated.

4 Answers 4

18

You'll need to get the terms from your input field and loop through all of them while building your DB query. You'll also need to set the table field in which you want the terms to be searched, in this the example the table field is name. Here's an untested example but you'll get the idea.

public function search() {

    $q = Input::get('myInputField');

    $searchTerms = explode(' ', $q);

    $query = DB::table('products');

    foreach($searchTerms as $term)
    {
        $query->where('name', 'LIKE', '%'. $term .'%');
    }

    $results = $query->get();

}
Sign up to request clarification or add additional context in comments.

4 Comments

I have a field called search that has a trigger that auto combines several key fields such as name, brand, type, year, ect. This way there is only one field to search through. I want the query to essentially break down to: SELECT * FROM products WHERE search LIKE '%burton%' AND search LIKE '%snowboards%' Is this not the correct way to go about this?
@MitchGlenn have you tested the code? There's a $query inside the foreach loop that does exactly what you say in your comment. Chainable where()'s build AND queries. You can see the queries produced by doing dd(DB::getQueryLog())
Should be DB::table(…) without 's'
How can you sanitate this query? I mean to insure, that the db term being searched is not actually another call to give permissions to a new user for example?
6

I made a plugin for laravel to make this! Hope you use it and give feedback. You can specify the relevance for each column and use information from other tables

https://github.com/nicolaslopezj/searchable

You can search like this

$products = Product::search($query)->get();

Comments

3

Controller Function 1

 public function search() {
    $q           = Input::get('searchKeyWords');
    $users       = DB::table('users');
        $results = $users->where('name', 'LIKE', '%'. $q .'%')
        ->orWhere('email', 'LIKE', '%'. $q .'%')
        ->orWhere('password', 'LIKE', '%'. $q .'%')
        ->get();
    return View::make('users.search')->with('users', $results);
}

Controller Function 2

 public function search() {
    $q = Input::get('searchKeyWords');
        $results = User::where('name', 'LIKE', '%'. $q .'%')
        ->orWhere('email', 'LIKE', '%'. $q .'%')
        ->orWhere('password', 'LIKE', '%'. $q .'%')
        ->get();
    return View::make('users.search')->with('users', $results);
}

Controller Function 3

public function search() {
        $results = User::where('name', 'LIKE', '%'. Input::get('searchKeyWords') .'%')
        ->orWhere('email', 'LIKE', '%'. Input::get('searchKeyWords') .'%')
        ->orWhere('password', 'LIKE', '%'. Input::get('searchKeyWords') .'%')
        ->get();
    return View::make('users.search')->with('users', $results);
}

Comments

1

This is sample when I try using Eloquent with many search terms

public function search() {

    $q = Input::get('myInputField');

    $searchTerms = explode(' ', $q);

    $query = $article->where('title', 'LIKE', "%{$keyword}%")
             ->orWhere('description', 'LIKE', "%{$keyword}%");

    foreach($searchTerms as $term)
    {
        $query = $query->orWhere('name', 'LIKE', '%'. $term .'%');
    }

    $results = $query->get();

}

You can also change ->get() function to other results like ->paginate(), and it should be like $results = $query->paginate(10);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.