Laravel Query Builder vs. Collection

Learn when Laravel executes a query, what get(), first(), and paginate() return, and where database filtering differs from Collection operations.

Best practices
Illustration of application infrastructure and operations

Laravel's Query Builder constructs SQL that runs in the database. A Collection works with values in PHP memory. Calling get() usually marks the handoff from a query builder to a collection, but other terminal methods return different types: first() returns one result or null, while paginate() returns a paginator.

The examples below target Laravel 12.x. Check the corresponding documentation if your application uses another version.

What each abstraction does

A query builder provides an application-facing API for constructing database queries:

$users = DB::table('users')
    ->where('votes', '>=', 100) // Becomes a SQL WHERE condition
    ->orderBy('created_at')
    ->get();                  // Executes this query

A Collection wraps data in a fluent PHP API:

$collection = collect(str_split('AABBCCCD'));

$chunks = $collection->chunkWhile(function ($value, $key, $chunk) {
    return $value === $chunk->last();
});

$chunks->map(fn ($chunk) => $chunk->values()->all())->all();
// [['A', 'A'], ['B', 'B'], ['C', 'C', 'C'], ['D']]

Here, chunkWhile() groups adjacent equal characters. Nothing in this operation requires a database.

Compare execution and resource use

Property Query Builder Collection
Execution location Generates SQL for the database Processes values in PHP
Data volume Can limit selected rows and columns before transfer Operates on the data already supplied
Typical operations where(), join(), groupBy(), get() map(), filter(), pluck(), chunk()
Performance Can use database indexes; inspect the execution plan Large materialized collections consume application memory; small transformations can be convenient
Evaluation Methods such as where() build the query; get() and first() execute it Ordinary collections are materialized; LazyCollection has separate lazy evaluation semantics

The same method name can mean different work

Both abstractions have methods such as where() and pluck(). The receiver determines where the work happens:

// The database filters rows before returning them.
DB::table('orders')->where('created_at', '>', '2024-01-01')->get();

// PHP filters the results after every row has been retrieved.
DB::table('orders')->get()->where('created_at', '>', '2024-01-01');

If the table contains a million rows, the second form retrieves all of them before filtering. Prefer database-side filtering, sorting, aggregation, and pagination when that reduces unnecessary transfer and memory use. This is not an absolute rule: a small collection already in memory may be the right place for a transformation. SQL and PHP comparisons can also differ, so preserve the intended semantics.

Collections are useful for reshaping results, grouping values for display, and calculating derived values after retrieval.

Where Eloquent fits

User::where(...)->get() starts with an Eloquent builder and returns an Illuminate\Database\Eloquent\Collection. This extends the base collection with model-related operations, such as load() for eager loading relationships.

That does not mean every Eloquent query returns a collection. first() returns a model or null; other terminal methods have their own return types.

Frequently asked questions

How can I tell which object I have?

Look at the terminal method and inspect the type with get_debug_type($value). Query Builder's get() returns a base collection of stdClass rows; Eloquent's get() returns a model collection. first() returns a row/model or null, and paginate() returns a LengthAwarePaginator. Do not pass null to get_class().

How do DB::table() and User::where() differ?

DB::table() creates a query builder without hydrating Eloquent models. User::where() creates an Eloquent query, and get() hydrates matching results as models. Both build a query before executing it.

Which Collection methods should I learn first?

Start with map, filter, pluck, groupBy, sortBy, chunk, first, count, sum, and toArray. Use the reference for less frequent operations and check whether a method preserves keys.

References

These examples illustrate API behavior; they have not been benchmarked against a production database.

Related reading

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting