$ lexprog.com

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

[July 23, 2026] Eloquent ORM

Eloquent JSON Columns: Queries

Eloquent JSON Columns: Queries

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

Eloquent JSON Columns: Queries

Tip: JSON Cast

protected $casts = ['settings' => 'array'];

Gotcha: JSON Where Clause (MySQL)

User::where('settings->theme', 'dark')->get();

Tip: JSON Where Clause (PostgreSQL)

User::where('settings->>theme', 'dark')->get();

Gotcha: whereJsonContains

Post::whereJsonContains('tags', 'laravel')->get();

Tip: JSON Update

User::where('id', 1)->update(['settings->theme' => 'dark']);

Gotcha: JSON Column Default

$table->json('settings')->default('{}');

Prevents null issues.

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

Querying JSON columns with whereJsonContains() and whereJsonLength() has improved dramatically, but these queries are still slower than indexed relational columns. A JSON column query in SQLite can't use indexes at all. I use JSON columns only for flexible metadata that's always read and written as a whole (like user preferences) and never for data that needs individual querying or indexing.

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

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