-
Notifications
You must be signed in to change notification settings - Fork 11.3k
[12.x] feat: Add $total param to the getPerPage() in Model #55482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
What does this fix? |
I want to specify inside the It would be much better if the paginate() function could be customized to first check if per_page was not present return |
@ah-rahimi
If you will return all table you will have memory issues but, anyway you can achieve that without changes in the core of laravel so, why did you open this PR? |
You are right, @macropay-solutions. |
In theory, this can be useful for populating drop down in filters with all values. But if you code it, it will for sure lead to out of memory issues so, you would need to put a max limit anyway to avoid that. We use limit=1000&simplePaginate=1 for this to avoid counting because we can use has_more_values from response to see if there are more results. |
$records = User::query()->paginate(fn ($total) => request('per_page', $total)); You can define a static method in your // on a helpers file
class BaseModel
{
public static function perPage($total)
{
return request('per_page', $total);
}
}
// on a controller
$records = User::query()->paginate(BaseModel::perPage(...)); Note that That also allows you to call the inner model's class BaseModel extends Model
{
public static function perPage($total)
{
if (! request()->has('per_page')) {
return $total;
}
return static::query()->newModelInstance()->getPerPage();
}
}
You can use the $records = User::query()->when(
request('per_page'),
// request has a per_page value
fn ($builder, $perPage) => $builder->paginate($perPage),
// request does not have a per_page value
fn ($builder) => $builder->get(),
); Or to reuse the logic across controllers, you can create an invokable class, and use the newly introduced query builder's <?php
namespace App;
use Illuminate\Database\Eloquent\Builder;
class CustomPaginator
{
public function __construct(
private readonly ?int $perPage,
) {}
public function __invoke(Builder $builder)
{
if (is_int($this->perPage) && $this->perPage > 0) {
return $builder->paginate($this->perPage);
}
return $builder->get();
}
} Then in your controllers: $records = User::query()->pipe(new CustomPaginator(request('per_page'))); Lastly, if you still think this PR is needed (I like it, as it makes the Adding a parameter to a public method is a breaking change. Any class overriding that method with a custom logic -- which is very likely to happen as that method is meant to be overridden -- will break due to the added parameter on the base class. |
@ah-rahimi If you want to avoid the memory issue when returning all table, you could try to stream the json to FE by using the lazy chunk if you eager load relations or the cursor chunk when no eager loading is involved Update Also you can have a look at streamJson doc Update |
I am closing this pull request because it lacks sufficient explanation, tests, or both. It is difficult for us to merge pull requests without these things because the change may introduce breaking changes to the framework. Feel free to re-submit your change with a thorough explanation of the feature and tests - integration tests are preferred over unit tests. Please include it's benefit to end users; the reasons it does not break any existing features; how it makes building web applications easier, etc. Thanks! |
No description provided.