Filtering a broken eloquent collection

I'm trying to filter out a paginated eloquent collection, but whenever I use any of the collection methods, I lose pagination.

$models = User::orderBy('first_name','asc')->paginate(20);

$models = $models->each(function($model) use ($filters) {
    if(!is_null($filters['type'])) {
        if($model->type == $filters['type'])
            return $model;
    }

    if(!is_null($filters['state_id'])) {
        if($model->profile->state_id == $filters['state_id'])
            return $model;
    }

    if(!is_null($filters['city_id'])) {
        if($model->profile->city_id == $filters['city_id'])
            return $model;
    }
});

return $models;

      

I am working with Laravel 4.2, is there a way to preserve the pagination?

+4


source to share


4 answers


Expanding on mininosis answer with your specific case:

//Start with creating your object, which will be used to query the database

$queryUser = User::query();

//Add sorting

$queryUser->orderBy('first_name','asc');

//Add Conditions

if(!is_null($filters['type'])) {
    $queryUser->where('type','=',$filters['type']);
}

if(!is_null($filters['state_id'])) {
    $queryUser->whereHas('profile',function($q) use ($filters){
        return $q->where('state_id','=',$filters['state_id']);
    });
}

if(!is_null($filters['city_id'])) {
    $queryUser->whereHas('profile',function($q) use ($filters){
        return $q->where('city_id','=',$filters['city_id']);
    });
}

//Fetch list of results

$result = $queryUser->paginate(20);

      



By applying proper conditions to your SQL query, you limit the amount of information returned to your PHP script and therefore speed up the process.

Source: http://laravel.com/docs/4.2/eloquent#querying-relations

+5


source


paginate () is a Builder function. If you already have a Collection object, then it does not have a paginate () function, so you cannot easily return it.

One solution is to have a different builder where you create the request, so you don't need to filter it later. Eloquent query builder is powerful enough, maybe you can turn it off.



Another option is to create your own custom paginator.

+1


source


You can do any query on your model before paginate.

I would like to give you some idea. I'll get all users by type

, sort

they will do paginate

at the end. The code will look like this.

$users = User::where('type', $filters['type'])->orderBy('first_name','asc')->paginate(20);

      

source: http://laravel.com/docs/4.2/pagination#usage

+1


source


None of the answers provide an answer to the real question that is possible in Laravel 5.2+:

How to filter the underlying Paginator collection without losing the Paginator object

Paginator is built on a base collection, but in fact, when you use any of the inherited methods, Collection

they return the base collection, not the full Paginator object: collection methods return collections to combine calls to the collection.

But you can extract, modify and add a collection like this:

$someFilter = 5;
$collection = $paginator->getCollection();
$filteredCollection = $collection->filter(function($model) use ($someFilter) {
  return $model->id == $someFilter;
});
$paginator->setCollection($filteredCollection);

      

0


source







All Articles