Search code examples
phplaravel-4

Laravel search query with multiple conditions


Newbie to PHP/Laravel here so please be patient.

I have a webpage that is searching based on 3 criteria for dogs , breed, sex and radius.

here is the relevant code:

search page

<div class="col-md-12 zero-pad-left zero-pad-right"> 
{{ Form::open(array('action' => array('DogsController@index'), 'class'=>'form width88', 'role'=>'search', 'method' => 'GET')) }} 
<div id="prefetch">
  {{ Form::text('search-breed', null, array('class' => 'typeahead form-group form-control', 'placeholder' => 'Search by breed here...')) }}
  {{ Form::text('sex', null, array('class' => 'form-group form-control', 'placeholder' => 'Search by sex here...')) }}
  {{ Form::text('miles', null, array('class' => 'form-group form-control', 'placeholder' => 'Search by distance here...')) }}




</div>
{{ Form::submit('Search', array('class' => 'btn btn-default search-bar-btn')) }}
{{ Form::close() }} 

ControllerPage

class DogsController extends \BaseController {

public function __construct()
{
    // call base controller constructor
    parent::__construct();

    // run auth filter before all methods on this controller except index and show
    $this->beforeFilter('auth', array('except' => array('show')));
}

/**
 * Display a listing of the resource.
 *
 * @return Response
 */
public function index()
{
    if (Input::has('search')) {
        $queryString = Input::get('search');
        $dogs = Dog::where('name', 'LIKE', "%$queryString%")->orderBy('name')->paginate(5);
    }

    elseif (Input::has('search-breed')) 
    {
        $dogs = Dog::whereHas('breed', function($q)     
        {
            $queryString = Input::get('search-breed');
            $q->where('name', 'LIKE', "%$queryString%");

        })->orderBy('name')->paginate(5);

    } //end elseif

    else {
        $dogs = Dog::orderBy('name')->paginate(5);
        } //end else

    return View::make('dogs.index')->with(array('dogs' => $dogs));
} //end function index()

when i enter a search for poodle, male, within 20 miles, the url shows as follows:

http://ruff-love.dev/dogs?search-breed=poodle&sex=M&miles=20

The search currently works ok when searching for just breed.

I cant seem to figure out the syntax to add the SEX and RADIUS criteria also. it should allow for those criteria to be null and still perform the query.

any advice would be greatly apprecaited


Solution

  • You can use query scopes http://laravel.com/docs/eloquent#query-scopes to make it verbose and easier in your controller (or wherever you will be doing it in future) then chain them according to your needs:

    // Dog model
    public function scopeSearchBreed($query, $breed)
    {
      $query->whereHas('breed', function ($q) use ($breed) {
        $q->where('name', 'like', "%{$breed}%");
      });
    }
    
    public function scopeWithinRadius($query, $radius)
    {
      $query->where(...); // do math here
    }
    

    Then all you need is this:

    public function index()
    {
      $q = Dog::query();
    
      if (Input::has('search'))
      {
         // simple where here or another scope, whatever you like
         $q->where('name','like',Input::get('search'));
      }
    
      if (Input::has('search-breed'))
      {
         $q->searchBreed(Input::get('search-breed'));
      }
    
      if (Input::has('sex'))
      {
         $q->where('sex', Input::get('sex'));
      }
    
      if (Input::has('radius'))
      {
         $q->withinRadius(Input::get('radius'));
      }
    
      $dogs = $q->orderBy(..)->paginate(5);
    
      // ...