How to Store Arrays and JSON in Laravel Eloquent
Use JSON plus an Eloquent cast for bounded structured data, but choose the cast deliberately, validate the shape, and normalize data that becomes relational.
TOPIC
Use JSON plus an Eloquent cast for bounded structured data, but choose the cast deliberately, validate the shape, and normalize data that becomes relational.
Any operation touching more than one table — where a partial failure would leave the data in a genuinely inconsistent state — belongs inside a transaction, not left to run as separate, independent queries.
Define the output grain first, filter source rows with WHERE, aggregate with GROUP BY, and use HAVING for conditions on grouped or aggregate results.
whereIn, whereNull, orWhere, and a handful of siblings cover almost every filtering need — the one that actually causes bugs is orWhere's grouping behavior when mixed with other conditions.
A search or filter form where every field is optional usually ends up as a wall of if statements around a query — when() folds each one into a single fluent chain instead.
"Users who have at least one order over $100" can't be expressed with a normal where() clause — whereHas() is specifically for filtering a query based on a related model's data.
MySQL and PostgreSQL both support indexing and querying inside a JSON column directly — Eloquent exposes that through arrow syntax and dedicated whereJson* methods, without raw SQL.
A loop of individual ->save() calls means one query per row — insert() (or upsert() for a merge) does it in one, at the cost of skipping model events and timestamps unless handled manually.
Every Eloquent timestamp is already a Carbon instance — the part that actually causes bugs is timezone handling: what gets stored, what gets displayed, and where the conversion between them should happen.
toSql(), getBindings(), and DB::listen() — the difference between seeing the query shape and seeing the actual query that ran, bindings included.
count(), isEmpty(), isNotEmpty(), and the N+1-query mistake people make trying to "optimize" an empty check on an Eloquent relationship.
PDO is the modern, framework-agnostic way to talk to MySQL from plain PHP — and prepared statements aren't optional if user input touches the query.