Mastering Laravel Eloquent: Advanced Tricks for Efficient Querying

ArjunAmrutiya
4 min readNov 16, 2023

1. Lazy Loading Relationships:

Lazy loading relationships can significantly improve performance by loading related data only when it’s needed. To enable lazy loading, you can use the with method.

$user = User::find(1);

// Lazy load the user's posts when needed
$posts = $user->posts;

2. Eager Loading Specific Columns:

When eager loading relationships, you can specify the columns you need, reducing the amount of data retrieved from the database.

$users = User::with(['posts' => function ($query) {
$query->select('id', 'title');
}])->get();

3. Global Scopes:

Global scopes allow you to define constraints that are automatically applied to all queries for a given model.

// Define a global scope for soft-deleted records
protected static function boot()
{
parent::boot();

static::addGlobalScope('softDeleted', function ($builder) {
$builder->where('deleted', 0);
});
}

4. Subquery in Select:

Use subqueries in the select method for complex queries without resorting to raw SQL.

$latestPosts = Post::select('title', 'created_at')
->whereIn('id', function ($query) {
$query->select('post_id')
->from('comments')
->where('approved', 1);
})
->get();

5. Polymorphic Relationships:

Polymorphic relationships allow a model to belong to more than one other type of model.

class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}

6. Using the tap Method:

The tap method allows you to tap into the query builder instance within a callback.

$users = User::where('active', 1)
->tap(function ($query) {
// Perform additional actions on the query builder
$query->orderBy('name');
})
->get();

7. Raw Expressions:

Leverage raw expressions for complex conditions or calculations.

$users = User::select(DB::raw('COUNT(*) as user_count, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();

8. Model Factories:

Use model factories to generate fake data for testing and seeding databases.

use Illuminate\Database\Eloquent\Factories\Factory;

class UserFactory extends Factory
{
protected $model = User::class;
public function definition()
{
return [
'name' => $this->faker->name,
'email' => $this->faker->unique()->safeEmail,
];
}
}

9. Query Scopes:

Organize your queries by defining reusable query scopes in your models.

class User extends Model
{
public function scopeActive($query)
{
return $query->where('active', 1);
}
}

// Usage
$activeUsers = User::active()->get();

10. Caching Queries:

Cache expensive queries to improve performance.

$users = Cache::remember('all_users', 60, function () {
return User::all();
});

11. Dynamic Relationships with when:

Conditionally define relationships based on certain criteria using the when method.

$relation = User::when($isAdmin, function ($query) {
return $query->hasMany('App\Post');
}, function ($query) {
return $query->hasMany('App\Comment');
})->get();

12. Custom Pivot Models:

When dealing with many-to-many relationships, use custom pivot models to add extra fields or behavior.

class RoleUser extends Pivot
{
// Custom fields or methods
}

13. Chunking Results:

Process large datasets efficiently using the chunk method to iterate over results in smaller segments.

User::orderBy('id')->chunk(200, function ($users) {
foreach ($users as $user) {
// Process each user
}
});

14. Conditional Relationships with unless:

Define relationships conditionally using the unless method.

$relation = User::unless($isGuest, function ($query) {
return $query->hasMany('App\Post');
})->get();

15. Global Query Scopes with Anonymous Classes:

Define global query scopes using anonymous classes for better organization.

protected static function boot()
{
parent::boot();

static::addGlobalScope(new class implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->where('active', 1);
}
});
}

16. Using pluck for Key-Value Pairs:

Efficiently retrieve key-value pairs using the pluck method.

$userRoles = User::pluck('role', 'id');

17. Querying JSON Columns:

Utilize the power of JSON columns in databases for flexible data storage.

$users = User::where('meta->status', 'active')->get();

18. Eloquent Resource Collections:

Transform your Eloquent models into API resources for clean and consistent data output.

class UserCollection extends ResourceCollection
{
public function toArray($request)
{
return [
'data' => $this->collection,
'meta' => ['key' => 'value'],
];
}
}

19. Counting Related Models:

Retrieve the count of related models efficiently.

$userCount = User::withCount('posts')->find(1);
echo $userCount->posts_count;

20. Customizing the Pivot Table Name:

Specify a custom table name for the pivot table in many-to-many relationships.

class User extends Model
{
public function roles()
{
return $this->belongsToMany('App\Role', 'user_roles');
}
}

Conclusion:

Mastering these advanced Laravel Eloquent tricks will empower you to tackle complex scenarios and optimize your database interactions. Experiment with these techniques to elevate your Laravel development skills and build robust, high-performance applications.

Stay tuned for more Laravel tutorials and tips on our blog!

Go forth and get more out of your content. Go forth and conquer Medium! (and while you’re at it, follow me on Medium! and feel free to Subscribe)

Found this post useful? Kindly tap the 👏 button below! :)

🌟 Enjoy my blogging content? Support my work by buying me a virtual coffee on BuyMeACoffee! Your contributions help fuel insightful tech articles. Join hands in making coding more accessible and exciting for all. https://www.buymeacoffee.com/arjunamrutiya🚀

--

--

ArjunAmrutiya

👋 Hey there! I'm Arjun Amrutiya, a passionate web developer and blogger who loves all things PHP, Laravel and Vue.js. Welcome to my Medium account!