Get number of rows in Laravel's Eloquent before using "take" and "skip"

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Getting the Total Row Count in Laravel Eloquent Before Using take() and skip()

As developers working with large datasets, pagination is an essential tool. When building interfaces that display data in chunks (like search results or administrative lists), using methods like take() and skip() is standard practice. However, a common pitfall arises when you need to display meaningful information to the user, such as "Showing 11 of 50 results," which requires knowing the total number of records available before limiting the output.

The challenge we face is accurately determining the total count that matches our complex where clauses before we apply the pagination limits. If we simply call count() after applying take() and skip(), the result will only reflect the limited set, not the true total.

This post will dive into the most efficient and idiomatic way to retrieve the total number of records in an Eloquent query before applying pagination offsets, ensuring both accuracy and performance.

The Problem with Post-Pagination Counting

Let's examine the scenario you described: filtering contacts by first and last name, and then applying take() and skip().

If you count the results after applying these methods, you are inherently counting only the subset of data requested.

php
$contacts = Contact::where(function($query) use ($request) {
    // ... where clauses for firstname and lastname ...
})
->take($iDisplayLength)
->skip($iDisplayStart)
->get(); // $contacts now only has the displayed subset

$iTotalRecords = count($contacts); // This will return $iDisplayLength - $iDisplayStart, not the total!

As you correctly observed in your thought process, attempting to calculate the total by running a separate query or manipulating the results after the fact is inefficient and messy. We need the total count from the database before any row reduction happens.

The Solution: Counting Before Pagination

The solution lies in executing the count() operation on the base query builder instance before applying the take() and skip() methods. This ensures that the count reflects all records matching the initial filtering criteria, regardless of what pagination limits are applied later.

This approach leverages Eloquent's ability to build a raw SQL aggregate query efficiently. The database engine handles the counting operation separately from the row retrieval process, making it highly performant.

Here is how you implement this pattern correctly:

php
$query = Contact::where(function($query) use ($request) {
    if (!empty($request['firstname'])) {
        $query->where('firstname', 'LIKE', "%{$request['firstname']}%");
    }   
    if (!empty($request['lastname'])) {
        $query->where('lastname', 'LIKE', "%{$request['lastname']}%");
    }     
});

// STEP 1: Get the total count immediately after applying filters.
$iTotalRecords = $query->count(); 

// STEP 2: Apply pagination (take/skip) and retrieve the results.
$contacts = $query->take($iDisplayLength)->skip($iDisplayStart)->get();

By executing $query->count() immediately after defining your where constraints, we instruct the database to calculate the total number of matching rows based on those filters before it has to fetch and limit the actual data. This results in a single, highly optimized query for counting, followed by a separate, limited query for fetching the data—a significant performance improvement over running two full queries.

Best Practices for Eloquent Performance

When dealing with large tables, understanding how Eloquent interacts with the database is crucial for scaling your application. Whenever you need counts or summarized information before pagination:

  1. Prioritize count(): Always use the model's count() method on the query builder object to get the total number of records matching your criteria.
  2. Use paginate() (When Appropriate): For most standard UI needs, leveraging Laravel's built-in paginate() method is often cleaner than manually managing take() and skip(). The paginate() method automatically handles retrieving the total count for you, making the code more readable and less error-prone.
  3. Indexing is Key: Ensure that any columns used in your where clauses (like firstname or lastname in our example) are properly indexed in your database. This dramatically speeds up both the filtering (where) and the counting (count()) operations, which is essential for handling large datasets efficiently.

By correctly separating the counting step from the retrieval step using the query builder methods, you ensure that your application remains fast, accurate, and scalable, adhering to the high standards set by frameworks like Laravel. For more in-depth knowledge on Eloquent relationships and performance tuning, exploring resources on laravelcompany.com is highly recommended.