$ lexprog.com

// notes from an old coder -- php, databases, and the occasional rant

[February 07, 2025] Eloquent ORM

Eloquent Relationship Caching

Eloquent Relationship Caching

────────────────────────────────────────────────────────

Eloquent Relationship Caching

Tip: Relations Are Cached

$post->author; // Query 1
$post->author; // No query - cached

Gotcha: load() Overwrites Cache

$post->load('author'); // Reloads and caches

Tip: Check if Loaded

if ($post->relationLoaded('author')) {
    // Already loaded
}

Gotcha: setRelation() for Manual Cache

$post->setRelation('author', $user);

Tip: unsetRelation() to Clear

$post->unsetRelation('author');

Forces reload on next access.

Gotcha: push() and Relations

push() saves the model AND its loaded relations. Unloaded relations are ignored.

Tip: Use cursor() for Memory-Neutral Iteration

When exporting 100K rows, get() loads everything into memory. cursor() uses yield and keeps memory flat regardless of row count. Perfect for artisan commands.

Tip: whereHas() vs load() — Two Different Things

whereHas() filters the parent query by relationship existence. load() eager-loads relationships AFTER the query. Mixing them up is a common source of logic bugs.

Gotcha: withCount() Adds a Subquery

withCount('comments') runs a correlated subquery on every row. On large tables, this can be slower than a separate query. Profile before relying on it.

Senior Insight

Caching relationship results is a common performance optimization, but it introduces consistency challenges. I've seen cached relationship data serve stale results after the underlying data changed because the cache key didn't include the model's updated_at timestamp. I always include a model-relevant invalidation key (like updated_at timestamp or a version counter) in cache keys for relationship data, and I invalidate cached relationships when the parent model is saved.

Source: Laravel Docs (https://laravel.com/docs/eloquent), Laravel News (https://laravel-news.com/), Freek.dev (https://freek.dev/tags/eloquent)

────────────────────────────────────────────────────────
<-- back to posts