Laravel Cloud is here! Zero-config managed infrastructure for Laravel apps. Deploy now.

6 Laravel Eloquent Secrets to improve your code

Published on by

6 Laravel Eloquent Secrets to improve your code image

Eloquent is the default ORM that ships with Laravel. It implements the Active-Record pattern and provides an easy way to interact with your database. Every single model represents a table in your database with which you can work. In this post, we’ll show you more or less hidden secrets, methods, and properties you might not know to improve your code.

Snake Attributes

Snake Attributes are an interesting one. Let’s take a look at what the code says:

/**
* Indicates whether attributes are snake cased on arrays.
*
* @var bool
*/
public static $snakeAttributes = true;

Very often, people make a mistake to use this property to change the way how to access properties. Many people believe that if they change this property, they can easily access the attributes using camel-case annotation. That’s not the case. We strongly advise against using it. It is merely there to define whether attributes are camel or snake-cased when the model is output as an array.

If you want to work camel-case based, we recommend you take a look at the package Eloquence by Kirk Bushell.

Pagination

If you use Laravel’s Eloquent ORM, you’re in luck. It provides an easy way to paginate results out of the box. You might be familiar with something like this:

$comments = Comment::paginate(20);

With this method, you can paginate the comment model with 20 items per page. Changing that value gives you the possibility to define how many items are displayed per page. If you do not specify anything, the default gets applied, which is 15.

Assume that you want to display comments in several places on your website. Always 30 comments per page. Then it would be bothersome if you have to pass the parameter 30 at every place. Therefore you can set a new default value directly on the model.

protected $perPage = 30;

Appending custom values to models

Eloquent has a great feature called “Accessors”. The feature allows you to add custom fields to models that don’t exist on the model or in the table. It doesn’t matter if you use existing values or define completely new ones. You can return anything. Here is an example of how Accessors work. Given there is a model called User where we put the code below.

function getFullNameAttribute() {
return sprintf('%s %s', $this->first_name, $this->last_name);
}

Now you have access to a full_name attribute on the post model, like this:

User::latest()->first()->full_name;

The problem is now if you return objects, like a collection, this attribute doesn’t get appended to the user model. Add the protected $appends attribute to your model. It accepts an array with one or multiple fields that should automatically be appended from now. This is how it looks like:

protected $appends = ['full_name'];

Mutators for non-existing columns

Mutators are the opposite of Accessors. You can use them for really cool stuff. For example, to convert different inputs. Let’s show you something. Imagine you want to save a kind of time period. Usually, you always save the smallest possible unit. In our case seconds. For UX reasons, the user doesn’t want to enter seconds, but for example, minutes in one place, or hours in another place. It can all be solved very quickly.

class Video extends Model
{
public function setDurationInMinutesAttribute($value)
{
$this->attributes['duration_in_seconds'] = $value * 60;
}
 
public function setDurationInHoursAttribute($value)
{
$this->attributes['duration_in_seconds'] = $value * 60 * 60;
}
}

What does it mean? It means that you can use the non-existent column duration_in_minutes on the model, but in the background, the column duration_in_seconds is updated. The same applies to the non-existent column duration_in_hours. This results in the following logic, for example:

class AnyController
{
public function store()
{
$video->update([
'title' => request('title'),
'duration_in_minutes' => request('duration_in_minutes'),
]);
}
}

This saves you the calculation in the controller, and you can simply use a non-existent column and use a mutator to map it correctly to the correct column while performing some calculations.

Eager loading with $with

Let’s talk a little about relations. By default, Laravel uses lazy loading. What does that mean in terms of relations? The good thing is that lazy loading saves memory because not all data has to be kept, and we load the data when we need it. Consider this code sample:

$comments = Comment::all();
foreach ($comments as $comment) {
echo $comment->user->name;
}

In the example above, we get all comments. Then we loop through the comments and display the username for each comment. The code works, but we run into a problem. Lazy loading now makes sure that the query to get the user is only executed when we want to output the username.

Welcome to your first N+1 problem. Why N+1? N is always the number of comments, and 1 is the query to get the comments at all. For example, if we have 500 comments, then the query to get all comments is fired once and then one query to get the corresponding user – per comment. So 500 + 1 queries. This means that as the number of comments increases, the number of queries increases as well.

To prevent it there is something called eager loading.

$comments = Comment::with('user')->get();
foreach ($comments as $comment) {
echo $comment->user->name;
}

That ends in two queries. The first query fetches all comments, and the second query immediately fetches all associated users. In the background, the following happens (simplified):

SELECT id, user_id, body FROM comments;
SELECT name FROM users WHERE user_id IN (1,2,3,4,5...);

Whether 10, 500 or 10000 comments are fetched at the end is not essential. Two queries remain.

You have now seen how you can use eager loading. But only how to use it manually. You can also automate the whole thing so that certain relations are always loaded automatically by eager loading. For this there is a property on the model.

protected $with = [];

So we can simply set the property protected $with = ['user']; on our Comment model, and from now, the user is automatically loaded at any time.

There are many more possibilities with eager loading. Loading of specific columns only, nested eager loading, multiple eager loadings, and much more. Head over to the Laravel documentation or deep dive into the core.

Model keys

From time to time, there is the need to fetch all IDs of a specific query. It does not matter whether this is a complex query or not. Most people would probably do the following:

User::all()->pluck('id');

This works great. But now you get a collection back. To get an array, you would have to pass it to the toArray() method again.

User::all()->pluck('id')->toArray();

In most cases, however, this can be shortened. Like this:

User::all()->modelKeys();

This method returns an array. In our case, the IDs. It is important to understand that this method does not always necessarily return IDs. It returns, as the name says, all primary keys as an array. The primary keys can be defined in the model. The default is id.

protected $primaryKey = 'id';
Stefan Bauer photo

Creator of PingPing.io ・ Author of Laravel Secret ・ Full Stack developer and a huge fanboy of Laravel, InertiaJS, Livewire and TailwindCSS.

Filed in:
Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

image
CodeRabbit

CodeRabbit is an AI-powered code review tool that specializes in PHP and Laravel, running PHPStan and offering automated PR analysis, security checks, and more

Visit CodeRabbit
Curotec logo

Curotec

World class Laravel experts with GenAI dev skills. LATAM-based, embedded engineers that ship fast, communicate clearly, and elevate your product. No bloat, no BS.

Curotec
Bacancy logo

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $3200/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
Cut PHP Code Review Time & Bugs into Half with CodeRabbit logo

Cut PHP Code Review Time & Bugs into Half with CodeRabbit

CodeRabbit is an AI-powered code review tool that specializes in PHP and Laravel, running PHPStan and offering automated PR analysis, security checks, and custom review features while remaining free for open-source projects.

Cut PHP Code Review Time & Bugs into Half with CodeRabbit
Get expert guidance in a few days with a Laravel code review logo

Get expert guidance in a few days with a Laravel code review

Expert code review! Get clear, practical feedback from two Laravel devs with 10+ years of experience helping teams build better apps.

Get expert guidance in a few days with a Laravel code review
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Harpoon: Next generation time tracking and invoicing logo

Harpoon: Next generation time tracking and invoicing

The next generation time-tracking and billing software that helps your agency plan and forecast a profitable future.

Harpoon: Next generation time tracking and invoicing
Lucky Media logo

Lucky Media

Get Lucky Now - the ideal choice for Laravel Development, with over a decade of experience!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Multi-tenant Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit

The latest

View all →
Laravel 12.44 Adds HTTP Client afterResponse() Callbacks image

Laravel 12.44 Adds HTTP Client afterResponse() Callbacks

Read article
Handle Nested Data Structures in PHP with the Data Block Package image

Handle Nested Data Structures in PHP with the Data Block Package

Read article
Detect and Clean Up Unchanged Vendor Files with Laravel Vendor Cleanup image

Detect and Clean Up Unchanged Vendor Files with Laravel Vendor Cleanup

Read article
Seamless PropelAuth Integration in Laravel with Earhart image

Seamless PropelAuth Integration in Laravel with Earhart

Read article
Laravel API Route image

Laravel API Route

Read article
Laravel News 2025 Recap image

Laravel News 2025 Recap

Read article