knocked
knocked

Reputation: 21

Laravel default pagination breaking with filter on the same table

I am using Laravel 9 and am displaying some data using the paginate method on the database. I also have a search field above my table and use it to filter out the result. While filtering, I filter the data and call the paginate method on it too. That's where the issue arises. Let's say I was on page number 6 before filtering and after filtering the result sums up in two page, but the paginate method redirect me to page 6 which in turn will show no results.

Below is my code example: For the first time page:

$modelData = Model::orderBy('id', 'DESC')->paginate(20);

After filtering:

$search         = $_GET['searchField'];
$modelData      = Model::where("name", "LIKE", "%{$search}%")->paginate(2);

I was expecting it to take me to the first page of the result, but it takes me the the page where i searched my list from.

EDIT: My Complete function:

public function index()
{
    $sortData   = $searchData = NULL;

    //CHECKS FOR SORTING, SEARCH AND BOTH
    if (isset($_GET['sort']) && !empty($_GET['sort']) && isset($_GET['searchField']) && !empty($_GET['searchField'])) {
        $search         = $_GET['searchField'];
        $modelData = Model::where("name", "LIKE", "%{$search}%")->orderBy($_GET['sort'], $_GET['direction'])->paginate(10);
        $sortData       = $_GET;
        $searchData     = $search;
    } elseif (isset($_GET['sort']) && !empty($_GET['sort'])) {
        $modelData = Model::orderBy($_GET['sort'], $_GET['direction'])->paginate(10);
        $sortData       = $_GET;
    } elseif (isset($_GET['searchField']) && !empty($_GET['searchField'])) {
        $search         = $_GET['searchField'];
        $modelData = Model::where("name", "LIKE", "%{$search}%")->paginate(10);
        $searchData     = $search;
    } else {
        $modelData = Model::orderBy('id', 'DESC')->paginate(10);
    }

    return view('content.view.list', compact(
        'modelData',
        'sortData',
        'searchData'
    ));
}

Upvotes: 0

Views: 552

Answers (1)

ronrun
ronrun

Reputation: 1234

  1. I think you should not use $_GET

     $request->query('sort')  
     $request->query('direction')
    
  2. Since you use !empty(), you don't need to use isset().

  3. You don't need $search, because

     $search         = $_GET['searchField'];  
     ...
     $searchData     = $search;
    

So

  $searchData = $_GET['searchField'];  
  1. You don't need $searchData,too. Because $sortData = $_GET.
    You already have whole $_GET, why do you want to define one of it's element again? $sortData['searchField']

  2. I think the English meaning of searchData is better than sortData. Becuar sortData means the data needed to sort, to order by. While searchData means the data needed to do the search task, do the filtering work. So searchData should be the $_GET.

I suggest:

public function index()
{
    $searchData= $request->query(); // This is $_GET

    // See what is your $_GET
    //echo "<pre>".print_r($searchData, 1)."</pre>"; exit;

    $model = Product::query(); //Initialize query builder

    if(!empty($searchData['searchField']))){
        $model->where('name', 'LIKE', '%'.$searchData['searchField'].'%');
    }

    if(!empty($searchData['sort']))){
        $sort = $searchData['sort'];
    }else{
        $sort = 'id'; // default use id
    }
    
    if(!empty($searchData['direction'])){
        $direction = $searchData['direction'];
    }else{
        $direction = 'DESC'; // default use desc
    }

    $model->orderBy($sort, $direction);

    // This can see the SQL content, and it should before result like paginate() or get(). I think...
    if(!empty($searchData['debug'])){
        $debugData['sql'] = $query->toSql();
        $debugData ['bidings'] = $query->getBindings();
        echo "<pre>".print_r($debugData , 1)."</pre>"; exit;
    }

    if(!empty($searchData['limit'])){
        $limit = $searchData['limit'];
    }else{
        $limit = 10;
    }

    $modelData = $model->paginate($limit)->appends($queries);

    return view('content.view.list', compact(
        'searchData',
        'modelData',
    ));

Upvotes: 1

Related Questions