Skip to content
OpenCloseEsc
Tips
  • Laravel
  • eloquent
  • database

Use sole() when exactly one row must match

first() hides a duplicate and firstOrFail() hides nothing more; sole() throws when there is no row and also when there is more than one.

1 min read

A lookup by email, slug or external id should match one row. first() quietly returns the first of two duplicates, and the bug surfaces weeks later as "the wrong customer got the invoice".

$customer = Customer::where('external_id', $externalId)->sole();

No row throws NoRecordsFoundException, two or more throw MultipleRecordsFoundException. Both extend RecordsNotFoundException, which the exception handler turns into a 404 in HTTP context, so a controller needs no extra check.

Works on the query builder too: DB::table('settings')->where('key', $key)->sole().