Optimizing Eloquent: Accessor Caching and Value Objects in Laravel
Laravel's Eloquent ORM is a powerful tool for working with databases, and it becomes even more potent when you leverage features like accessor caching and value objects. Let's dive into these concepts and see how they can enhance your Laravel applications.
Accessor Caching with shouldCache()
When dealing with computationally intensive accessors, caching can significantly improve performance. Laravel provides the shouldCache()
method to easily cache the results of your accessors.
Here's how you can implement it:
class User extends Model
{
protected function expensiveComputation(): Attribute
{
return Attribute::make(
get: fn ($value) => $this->heavyCalculation($value)
)->shouldCache();
}
private function heavyCalculation($value)
{
// Simulate a time-consuming operation
sleep(2);
return "Processed: " . $value;
}
}
In this example, expensiveComputation
is an accessor that performs a heavy calculation. By calling shouldCache()
, we ensure that the result is cached after the first access, avoiding redundant computations in subsequent calls.
Value Objects and Auto-Syncing
Laravel's Eloquent also seamlessly handles value objects, automatically syncing changes back to the model. This feature allows you to work with complex data structures more intuitively.
Here's an example:
class User extends Model
{
protected function address(): Attribute
{
return Attribute::make(
get: fn ($value) => new Address($value),
set: fn (Address $value) => $value->toArray()
);
}
}
class Address
{
public function __construct(public string $street, public string $city) {}
public function toArray()
{
return ['street' => $this->street, 'city' => $this->city];
}
}
In this setup, you can work with the address
attribute as an Address
object:
$user = User::find(1);
$user->address->city = 'New York';
$user->save(); // The changes to the Address object are automatically synced
Disabling Object Caching
While object caching is generally beneficial, there might be scenarios where you want to disable it. Laravel provides the withoutObjectCaching()
method for such cases:
class User extends Model
{
protected function dynamicData(): Attribute
{
return Attribute::make(
get: fn ($value) => new DynamicData($value)
)->withoutObjectCaching();
}
}
This is particularly useful for attributes that need to be re-evaluated every time they're accessed, even within the same request cycle.
By leveraging these Eloquent features, you can create more efficient, expressive, and maintainable Laravel applications. Whether you're dealing with complex computations, structured data, or dynamic attributes, Laravel provides the tools to handle these scenarios elegantly.
If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!