lorisleiva/laravel-add-select
Laravel Add Select is a small Laravel package that simplifies appending select columns to existing queries. It provides a fluent helper for adding columns or subqueries to Eloquent and query builder selects without rewriting existing select clauses, making incremental query composition cleaner and m...
Install the package with Composer:
composer require lorisleiva/laravel-add-select
The package provides a trait that lets you attach subselect queries as aliased columns on Eloquent models. Add the trait to the model you want to query:
use Lorisleiva\AddSelect\AddSelect;
class User extends Model
{
use AddSelect;
}
The first use case is usually adding a computed column to avoid loading an entire relation. For example, get each user’s most recent login timestamp without eager-loading every login row:
$users = User::addSelect([
'last_login_at' => Login::select('created_at')
->whereColumn('user_id', 'users.id')
->latest()
->limit(1),
])->get();
echo $users->first()->last_login_at;
Check the README first. The package is small and the exact trait name / method signature may differ slightly. The pattern above matches Laravel’s native subselect syntax and is the most common way this package is used. If you’re on Laravel 6+, native
addSelectalready supports subqueries, so you may not need the package at all.
Wrap subselects in query scopes. Keep controllers clean by defining reusable scopes on the model:
public function scopeWithLastLogin($query)
{
$query->addSelect([
'last_login_at' => Login::select('created_at')
->whereColumn('user_id', 'users.id')
->latest()
->limit(1),
]);
}
// Usage
User::withLastLogin()->paginate();
Reuse subselect definitions as methods. If the same subselect is needed in multiple places, extract it to a method that returns a query builder:
public function lastLoginSubselect()
{
return Login::select('created_at')
->whereColumn('user_id', 'users.id')
->latest()
->limit(1);
}
// Usage
User::addSelect(['last_login_at' => $this->lastLoginSubselect()])->get();
Combine multiple subselects in one query. This is efficient because each subselect is a single correlated query, avoiding N+1 problems:
User::addSelect([
'last_login_at' => Login::select('created_at')
->whereColumn('user_id', 'users.id')
->latest()
->limit(1),
'posts_count' => Post::selectRaw('count(*)')
->whereColumn('user_id', 'users.id'),
])->get();
Use with API resources. Computed columns are plain model attributes, so they serialize naturally:
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'last_login_at' => $this->last_login_at,
'posts_count' => $this->posts_count,
];
}
}
Prefer native helpers when they fit. For simple counts and sums, Laravel’s withCount and withSum are more readable and often better optimised. Use this package when you need a custom correlated subquery that those helpers don’t cover.
Combine with eager loading carefully. Subselects and with() solve different problems. Use subselects for scalar values (counts, latest timestamps) and with() for full relations you actually need to render.
Correlated subqueries can be slow. Each row may execute the subquery. Add indexes on the correlated columns (user_id) and any ordering columns (created_at) used inside the subselect. For large datasets, consider denormalised counters or caching instead.
Alias collisions. The alias you choose (last_login_at) must not clash with an existing column or another subselect. Use distinct, descriptive aliases.
Table aliasing breaks correlation. If you alias the main table (User::from('users as u')), update every whereColumn reference to the alias. The subselect must correlate against the exact table name or alias used in the outer query.
Debug with SQL output. Use ->toSql() and ->getBindings() on the query before executing, or enable Laravel’s query log, to verify the subselect is generated as expected.
Package maintenance is a risk. The last release was in 2020 and the repository has ~32 stars. Test thoroughly on your Laravel version. For new projects, prefer native addSelect with subqueries, selectSub, withCount, or withSum.
Native alternatives are often enough. Laravel 6+ supports subqueries directly in addSelect:
User::addSelect([
'last_login_at' => Login::select('created_at')
->whereColumn('user_id', 'users.id')
->latest()
->limit(1),
])->get();
If the package feels unnecessary, you can drop it and use the native syntax.
Extension points. If you need custom behaviour, you can define your own subselect builder classes or wrap the package’s trait method in a base model. Check the package source for the exact method you can override.
Version pinning. Because the package is unmaintained, pin a known-working version in composer.json and cover critical queries with tests so future Laravel upgrades don’t silently break subselect generation.
How can I help you explore Laravel packages today?