filtering a paginated eloquent collection

旧巷老猫 提交于 2020-06-14 09:38:35

问题


I am trying to filter a paginated eloquent collection, but whenever I use any of the collection methods, I lose the 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 any way to persist the pagination?


回答1:


Expanding on mininoz's 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 the proper conditions to your SQL query, you are limiting the amount of information that comes back to your PHP script, and hence speeding up the process.

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




回答2:


None of the answers provide an answer to the actual question, which is possible in Laravel 5.2+:

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

The Paginator is built on an underlying collection, but indeed when you use any of the inherited Collection methods they return the underlying collection and not the full Paginator object: collection methods return collections for chaining together collection calls.

But you can eject, modify and inject the collection as follows:

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



回答3:


paginate() is function of Builder. If you already have Collection object then it does not have the paginate() function thus you cannot have it back easily.

One way to resolve is to have different builder where you build query so you do not need to filter it later. Eloquent query builder is quite powerful, maybe you can pull it off.

Other option is to build your own custom paginator yourself.




回答4:


You can do some query on your model before do paginate.

I would like to give you some idea. I will get all users by type, sort them and 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




回答5:


This was suitable for me;

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

if($users->count() < 1){
  return redirec($users->url(1));
}


来源:https://stackoverflow.com/questions/29843250/filtering-a-paginated-eloquent-collection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!