23

Pagination search results

I have just started with Laravel and I am trying to make a search function with proper pagination. The function works for page one but on page two it doesn't. I think it's not giving the results to the next page but I can't seem to find an answer.


this is my search function inside IndexController:

public function search()
{
    $q = Input::get('search');

    # going to next page is not working yet
    $product = Product::where('naam', 'LIKE', '%' . $q . '%')
        ->orWhere('beschrijving', 'LIKE', '%' . $q . '%')
        ->paginate(6);

    return view('pages.index', compact('product'));
}

this is my route:

Route::post('search{page?}', 'IndexController@search');

this is the URL of page two:

/search?page=2

this is how I show my pagination:

{{ $product->appends(Request::get('page'))->links()}}

the error:

MethodNotAllowedHttpException in RouteCollection.php line 218:

Get error on request.

Route:

Route::get('search/{page?}', 'IndexController@search');

Error:

MethodNotAllowedHttpException in RouteCollection.php line 218:
in RouteCollection.php line 218
at RouteCollection->methodNotAllowed(array('GET', 'HEAD')) in RouteCollection.php line 205
at RouteCollection->getRouteForMethods(object(Request), array('GET', 'HEAD')) in RouteCollection.php line 158
at RouteCollection->match(object(Request)) in Router.php line 780
at Router->findRoute(object(Request)) in Router.php line 610
at Router->dispatchToRoute(object(Request)) in Router.php line 596
at Router->dispatch(object(Request)) in Kernel.php line 267
at Kernel->Illuminate\Foundation\Http\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in CheckForMaintenanceMode.php line 46
at CheckForMaintenanceMode->handle(object(Request), object(Closure)) in Pipeline.php line 137
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 33
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in Pipeline.php line 104
at Pipeline->then(object(Closure)) in Kernel.php line 149
at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 116
at Kernel->handle(object(Request)) in index.php line 53

I hope my question is clear and in the right format. Thank you in advance (sorry for my bad English)


Answer:

I ended up using the answer of this post in combination with some help of this post

I used a post function for the initial search and a get function for the following pages. This was possible because I'm now giving my search to the URL.


EDIT:

  • added the initial error.
  • added the Route::get error
  • added answer
Community
  • 1
  • 1
Casper Spruit
  • 944
  • 1
  • 13
  • 31

11 Answers11

49

If you want to apply filters to the next page you should add them to your paginator like this:

$product = Product::where('naam', 'LIKE', '%' . $q . '%')
        ->orWhere('beschrijving', 'LIKE', '%' . $q . '%')
        ->paginate(6);
$product->appends(['search' => $q]);

And change your route from post to get:

Route::get('search', 'IndexController@search');
Andrej
  • 7,474
  • 1
  • 19
  • 21
  • It seems my brain is not working 100% until noon. This is indeed correct answer. To this question. Also, shouldn't it be `Route::get('search/{page?}')`? – Skysplit Sep 05 '16 at 08:34
  • 2
    @Skysplit Frankly speaking, {page?} should be removed from url completely. – Andrej Sep 05 '16 at 08:37
  • Yeah, you're right. It would be useful if there is a page resolver added. – Skysplit Sep 05 '16 at 08:39
  • this works for going to page 2 but to post my search I need a post. Any work arounds for that? – Casper Spruit Sep 05 '16 at 08:39
  • 1
    @casperspruit I'm not sure why you need to `POST` search. Usually you use `POST` when you want to change application state/data. Searching does not change anything, so you can use `GET`. If you really want to use `POST`, then you have to override paginator view and use `post` method in it. – Skysplit Sep 05 '16 at 08:42
  • You can't use link because it will generate get request. You should add javascript that will catches click on the link, fetches the page, combine data and sends the post request. @casperspruit – Andrej Sep 05 '16 at 08:42
  • I dont mind using GET but this gives me an error stating that I cant use GET. This is with the initial search, for page 2 I need to use POST. – Casper Spruit Sep 05 '16 at 08:45
  • @CasperSpruit change you route definition as I proposed. – Andrej Sep 05 '16 at 08:49
  • Did you remove {page?}? @CasperSpruit – Andrej Sep 05 '16 at 09:04
  • I fixed it by using 2 routes and a different link echo. How should I close this question since I also want to credit you guys? Its saving the search in the url now. – Casper Spruit Sep 05 '16 at 09:06
  • @CasperSpruit well, if you think that my answer helped to solved the issue just accept it. – Andrej Sep 05 '16 at 09:08
  • It deffinitly did. Thank you very much! – Casper Spruit Sep 05 '16 at 09:09
  • Great buddy, works like a charm. you saved so many time. – vahid sabet Jul 14 '20 at 06:53
  • i think that this is a very neat solution, worked perfectly for me! [+1] – kapitan Aug 18 '20 at 01:39
17

a quick way in view (Lavarel 5.7)

$product->appends(Request::all())->links();
ytdm
  • 1,069
  • 1
  • 12
  • 15
3
Route::get('product', function () {
    $product= App\product::paginate(15);

    $product->setPath('custom/url');

});

View:

{{ $product->appends(['search' => Request::get('page')])->links() }}
Joci93
  • 803
  • 3
  • 10
  • 24
2

I assume you want to change pages with urls like this search/1, search/2? First of all your route should be probably Route::post('search/{page?}').

I'm not sure if only this change will work, but if it does not, you have to resolve page like this

public function search(\Illuminate\Http\Request $request, $page = 1)
{
    $q = $request->get('search');

    \Illuminate\Pagination\Paginator::currentPageResolver(function () use ($page) {
        return $page;
    });

    # going to next page is not working yet
    $product = Product::where('naam', 'LIKE', '%' . $q . '%')
        ->orWhere('beschrijving', 'LIKE', '%' . $q . '%')
        ->paginate(6);

    return view('pages.index', compact('product'));
}
Skysplit
  • 1,875
  • 12
  • 16
  • Edit: My urls are like search?page=2, the pagination does it by default, so how should I change this. Your function gives the same error as mine "MethodNotAllowedHttpException in RouteCollection.php line 218:" – Casper Spruit Sep 05 '16 at 08:37
2
$searchdata =  \Request::get( 'inputTextFieldname' ); \make as global
$searchresult = Modelname::where ( 'blogpost_title', 'LIKE', '%' .$searchdata . '%' )->paginate(2);
return view( 'search', compact('searchresult') );

and in your view page

{{$searchresult->appends(Request::only('inputTextFieldname'))->links()}}

make your route to get method

Route::get('/search', ['as' => 'search', 'uses' => 'searchController@index']);

this will be done, thanks,

ram12393
  • 1,284
  • 3
  • 14
  • 29
Y. Joy Ch. Singha
  • 3,056
  • 24
  • 26
2

in my case, i've laravel 5.7 installed.

$perPage = $request->per_page ?? 10;

$data['items'] = User::where('name', 'like', '%'. $request->search . '%')
                         ->paginate($perPage)
                         ->appends(['search' => $request->search, 'per_page' => $request->per_page]);

    return view('users.index', $data);

and my view files codes are

for per_page select dropdown and search area

<form role="form" class="form-inline" method="get" action='{{ url('/user') }}'>
 <div class="row">
  <div class="col-sm-6">
   <div class="dataTables_length">
     <label>Show
     <select name="per_page"
       onchange="this.form.submit()"
       class="form-control input-sm">
      <option value=""></option>
      <option value="10" {{ $items->perPage() == 10 ? 'selected' : '' }}>10
      </option>
      <option value="25" {{ $items->perPage() == 25 ? 'selected' : '' }}>25
      </option>
      <option value="50" {{ $items->perPage() == 50 ? 'selected' : '' }}>50
      </option>
     </select>
     entries
     </label>
    </div>
   </div>

<div class="col-sm-6">
 <div class="dataTables_filter pull-right">
  <div class="form-group">
   <label>Search: &nbsp;
   <input type="search" name="search" class="form-control input-sm"
   placeholder="Name" value="{{ request()->search }}">
   </label>
  </div>
 </div>
</div>

and my pagination generator code

{{ $items->appends(['search' => request()->search, 'per_page' => request()->per_page])->links() }}
sh6210
  • 4,190
  • 1
  • 37
  • 27
2

The easy way to solve this use your UsersController.php by adding ->withQueryString() to ->paginate(6)

public function search()
{
$q = Input::get('search');

# going to next page is not working yet
$product = Product::where('naam', 'LIKE', '%' . $q . '%')
    ->orWhere('beschrijving', 'LIKE', '%' . $q . '%')
    ->paginate(6)->withQueryString();

return view('pages.index', compact('product'));
}

and in the view file

{{$product->links()}}
Muhammad Dyas Yaskur
  • 6,914
  • 10
  • 48
  • 73
Sachin Saini
  • 359
  • 2
  • 10
  • Please edit your question to explain what `withQueryString()` does in this context. – miken32 Dec 09 '21 at 17:32
  • Hi miken , the function withQueryString() will work on laravel 7 & 8 . it will make the URL request ?page=2 as you can see in the official documentation https://laravel.com/docs/8.x/pagination#appending-query-string-values – Sachin Saini Dec 09 '21 at 18:05
  • As I said, [edit] your question to explain this. – miken32 Dec 09 '21 at 18:07
1

For pagination, you should create a simple form:

<form action="{{URL::to('/search')}}" method="post">
    <input type="hidden" name="query"/>
    <select name="pages">
    @for($p = 1; $p < $products->lastPage(); $p++ )
        <option value="{{ $p }}">{{ $p }}</option>
    @endfor
    </select>
</form>

Pagination methods are here:

$results->count()
$results->currentPage()
$results->firstItem()
$results->hasMorePages()
$results->lastItem()
$results->lastPage() (Not available when using simplePaginate)
$results->nextPageUrl()
$results->perPage()
$results->previousPageUrl()
$results->total() (Not available when using simplePaginate)
$results->url($page)
Kemal Y
  • 59
  • 1
  • 2
  • 6
1

If you are using search form with GET method then use something like these to preserve pagination withing search results.

 public function filter(Request $request)
    {        
        $filter = $request->only('name_operator','name_value','email_operator','email_value', 'phone_operator','phone_value',   'gender_value', 'age_operator','age_value');
        $contacts = $this->repo->getFilteredList(array_filter($filter));
        $contacts->appends($filter)->links(); //Continue pagination with results
        return view('dashboard::index', compact('contacts'))->withInput($request->all());
    }
Amit Shah
  • 7,771
  • 5
  • 39
  • 55
-1

In your view file where you display pagination...

{{ $results->appends(Request::except('page'))->links() }}

appends keeps the query string value except "page".

Rahul Gupta
  • 991
  • 4
  • 12
Miraj Khandaker
  • 772
  • 10
  • 11
-1

use any in route Instead post Route::any('search', 'IndexController@search');