Model::limit
Caps how many rows an Eloquent query returns by setting the SQL LIMIT clause.
Model::limit(int $value): Illuminate\Database\Eloquent\BuilderParameters
| Parameter | Type | Description |
|---|---|---|
$$value | int | The maximum number of rows the query may return. Applied to the union's limit instead when the query contains unions. |
Return value
Illuminate\Database\Eloquent\BuilderThe same query builder instance, so the call can be chained.
Changelog
- PHP 12.0.0chunk(), chunkById() and lazy() were fixed to honour a user-defined limit and offset instead of overwriting them.
limit sets the SQL LIMIT clause on an Eloquent query and hands the builder back, so it can sit anywhere in a chain before get, first or pluck. take is a straight alias — both compile to identical SQL. Its partner is offset, aliased as skip, which sets the starting row.
When to reach for it
Use it when you pick the boundary yourself: the ten highest-scoring rows, a sample while poking at data in Tinker, a correlated subquery that must yield exactly one row. If a human is clicking through pages, use paginate instead — it derives the limit and offset from the request. If you are walking an entire table, use chunk.
What trips people up
A LIMIT with no ORDER BY has no defined meaning in SQL. MySQL usually returns rows in primary-key order, right up until an index change makes it stop. Always pair limit with orderBy.
Also, this is the query-level limit, not Collection::take. Calling ->get()->take(5) pulls every matching row into PHP first and then throws most of them away; ->limit(5)->get() asks the database for five.
Example
<?php
use App\Models\Flight;
// The five most expensive flights...
$flights = Flight::orderByDesc('price')->limit(5)->get();
echo $flights->count(); // 5
echo $flights->first()->price; // 899.00
// take() is the alias; offset()/skip() move the window.
$second = Flight::orderBy('id')->offset(5)->take(5)->get();
echo $second->pluck('id')->implode(', '); // 6, 7, 8, 9, 10When to use it
- Show a leaderboard of the ten highest-scoring users.
- Grab a handful of rows to inspect a table's shape without loading it all.
- Build manual offset paging for an API endpoint that takes its own page parameters.
- Constrain a subquery inside addSelect to a single row.
Frequently asked questions
What is the difference between limit() and take() in Laravel?
There is none — take() calls limit() and nothing else. Both set the same property on the query and produce the same SQL, so pick whichever reads better in your chain.
Why does limit() return all rows sometimes?
Because a negative value is silently ignored: the framework only applies the limit when the argument is greater than or equal to zero. A computed value that goes negative, such as limit($total - $used), leaves the query completely unbounded.
How do I skip rows before the limit in Eloquent?
Chain offset() or its alias skip() before or after limit() — order in the chain does not matter, since both simply set properties on the query object. Offset clamps negative values to zero.
More examples
Limiting in the database versus limiting in PHP
Both variables hold five models, so the bug is invisible in the output. The difference is the query: the first sends limit 5 to the server, the second hydrates the whole table into memory first. On a table with a million rows the second form is what exhausts the memory limit.
<?php
use App\Models\Flight;
// Asks the database for 5 rows: "select * from flights order by price desc limit 5"
$cheap = Flight::orderByDesc('price')->limit(5)->get();
// Asks the database for EVERY row, then discards all but 5 in PHP.
$expensive = Flight::orderByDesc('price')->get()->take(5);
echo $cheap->count(); // 5
echo $expensive->count(); // 5Offset paging by hand
This is exactly what paginate() does internally, minus the count query and the link generation. Use it when the page number comes from somewhere other than the HTTP request, such as a queued job or a console command.
<?php
use App\Models\Flight;
$perPage = 25;
$page = 3;
$flights = Flight::where('active', 1)
->orderBy('id')
->offset(($page - 1) * $perPage)
->limit($perPage)
->get();
echo $flights->count(); // 25
echo $flights->first()->id; // 51
echo $flights->last()->id; // 75A limit inside a subquery
The limit(1) is what makes the subquery legal — a scalar subselect must return at most one row. Without the orderByDesc the database is free to pick any matching flight, so the ordering is doing real work here, not decoration.
<?php
use App\Models\Destination;
use App\Models\Flight;
$destinations = Destination::addSelect(['last_flight' => Flight::select('name')
->whereColumn('destination_id', 'destinations.id')
->orderByDesc('arrived_at')
->limit(1)
])->get();
echo $destinations->first()->name; // Paris
echo $destinations->first()->last_flight; // London to Paris
Discussion