19

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

4 Answers 4

31

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);

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

2 Comments

this looks real good but it looks to me like you set it up for three distinct searches breed, or sex or radius correct? what i was really hoping to do was have a search for breed (which already works as is) and then add in the options of sex and/or radius. I like your code, its easy ti understand to my novice eyes but can you refactor it so it does that?
You get it wrong. What it does is 1 prepare query, 2 add every filter that is necessary, 3 get the result from built query. As a result you will get dogs matching all given constraints, thanks to the if statements.
3

Here's one possible solution, I think there are probably others. Create an empty query builder with the query() function and add the non-null clauses to it, then call the paginate() function at the end.

$builder = Dogs::query();
if (Input::has('search')) {
    $queryString = Input::get('search');
    $builder->where('name', 'LIKE', "%$queryString%");
}
// ... more clauses from the querystring
$dogs = $builder->orderBy('name')->paginate(5);

4 Comments

the 'search' is used for searching for dog by name.
Not sure what you mean, that's what this code will do.
sorry i stepped away and the website wouldn't let me finish my comments. the 'search' is used for searching for dog by name. the one i was really trying to work on 'search-breed'. if i take your code and just switch the name to 'search-breed' and insert it in the elseif section, should that work?
You can use this principle to add gender and radius to your breed search. The idea is you build up a series of where clauses based on what's the querystring, you can have any combination of breed, gender and radius. I illustrated the free text search because it was a simpler example of this principle.
1
$builder = Dogs::query();
$term = Request::all();
if(!empty($term['breed'])){
    $builder->where('breed','=',$term['breed']);
}
if(!empty($term['sex'])){
    $builder->where('sex','=',$term['sex']);
}
if(!empty($term['radius'])){
    $builder->where('radius','=',$term['radius']);
}

$result = $builder->orderBy('id')->get();

Comments

0
$area = Area::query();

if (Input::has('search')) {
    $queryString = Input::get('search');
    $area->where('name', 'LIKE', "%" . $queryString . "%");
}

$result = $area->orderBy('name')->paginate(5);

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.