M
MeshWorld.
Laravel Eloquent PHP Database 5 min read

Laravel firstOrCreate(): Find or Create a Record

Vishnu
By Vishnu
| Updated: Mar 27, 2026

firstOrCreate() is a Laravel Eloquent method that searches for a record matching a set of attributes, and if none exists, creates and saves a new one — all in a single call. Available in Laravel 10, 11, and 12, it eliminates the manual if/else pattern of checking for a record and creating it yourself. You get the model back either way, already persisted in the database.

:::note[TL;DR]

  • Model::firstOrCreate($attributes, $values) finds the first match or creates a new record
  • First argument: the search criteria (used in the WHERE clause)
  • Second argument: extra fields set only when creating a new record (not used for searching)
  • Automatically saves to the database — no ->save() call needed
  • Differs from firstOrNew(): that method returns an unsaved instance you must save manually :::

What is the syntax for firstOrCreate()?

The method accepts two arrays. The first is required; the second is optional.

Model::firstOrCreate(array $attributes, array $values = [])

The $attributes array is the search criteria — these fields are used in the WHERE clause. If no match is found, Laravel creates a new record using a merge of both $attributes and $values. The $values fields are only applied when creating, not when searching.

How does firstOrCreate() work in practice?

Scenario: A user signs in with Google OAuth. You call User::firstOrCreate(['email' => $oauthEmail], ['name' => $oauthName, 'provider' => 'google']). If that email already exists in your users table, you get the existing record back. If it doesn’t, Laravel creates a new user with the email, name, and provider — and saves it. No if/else. No separate save().

Without firstOrCreate(), the same logic takes more code. Here’s the manual approach:

$email = $oauthUser->getEmail();
$user = User::where('email', $email)->first();

if ($user === null) {
    $user = User::create([
        'email'    => $email,
        'name'     => $oauthUser->getName(),
        'provider' => 'google',
    ]);
}

With firstOrCreate(), that entire block collapses to one line:

$user = User::firstOrCreate(
    ['email' => $oauthUser->getEmail()],
    [
        'name'     => $oauthUser->getName(),
        'provider' => 'google',
    ]
);

The result is the same. The email is the search key. name and provider are only written when a new record is being created — they don’t affect the lookup.

What is the difference between the two parameters?

The split matters. First argument: fields used to find the record. Second argument: fields added only on creation.

Consider this call:

$tag = Tag::firstOrCreate(
    ['slug' => 'laravel-tips'],
    ['name' => 'Laravel Tips', 'color' => '#FF6347']
);

Laravel runs SELECT * FROM tags WHERE slug = 'laravel-tips' LIMIT 1. If found, it returns that record — it doesn’t touch name or color. If not found, it inserts a new row with slug, name, and color all set.

This is intentional. You don’t want to accidentally overwrite existing field values during a “find or create” operation.

What is the difference between firstOrCreate() and firstOrNew()?

The key difference is persistence. firstOrCreate() saves to the database automatically. firstOrNew() returns an unsaved model instance — you call ->save() yourself.

MethodSaves to DB?Use when…
firstOrCreate()Yes, immediatelyYou want the record saved without extra steps
firstOrNew()No, manual save requiredYou need to modify the instance before saving

If you need to enrich the model with data from an external API before saving, use firstOrNew(). If you just want a guaranteed-persisted record with no extra logic, firstOrCreate() is the right call.

Can I use firstOrCreate() with unique constraints?

Yes, and it’s designed for exactly this. firstOrCreate() is safe to use with unique columns as search criteria. It’s commonly used for seeding tags, categories, roles, and similar reference data.

// Seeding roles without duplicates
$roles = ['admin', 'editor', 'viewer'];

foreach ($roles as $role) {
    Role::firstOrCreate(['name' => $role]);
}

Running this multiple times won’t create duplicates. Each iteration either finds the existing role or creates it fresh.

:::warning firstOrCreate() is not atomic by default. In high-concurrency scenarios, two requests can simultaneously find no matching record and both attempt to create one, causing a duplicate key error. In Laravel 10+, consider wrapping it in a try/catch for UniqueConstraintViolationException, or use updateOrCreate() if you want to also update existing records. :::

Summary

  • firstOrCreate($attributes, $values) finds a record by $attributes or creates a new one with both arrays merged
  • The second argument is only used when creating — it never affects the search
  • The new record is saved to the database immediately — no ->save() needed
  • Use firstOrNew() instead when you need to modify the model instance before persisting it
  • In concurrent environments, wrap in a try/catch to handle potential unique constraint violations

FAQ

Does firstOrCreate() fire model events? Yes. If a new record is created, the creating and created model events fire. If an existing record is found, no events fire.

Can I use firstOrCreate() with composite keys? Yes. Pass multiple fields in the first argument to search on multiple columns simultaneously: Model::firstOrCreate(['user_id' => 1, 'tag_id' => 5]).

Does firstOrCreate() return different values based on whether it created or found a record? No. It always returns the model instance. To check whether the record was just created, access the wasRecentlyCreated attribute: if ($user->wasRecentlyCreated) { ... }.

Is firstOrCreate() available in Laravel 10, 11, and 12? Yes. It’s a long-standing Eloquent method, unchanged across all three versions.

What if I need to update an existing record during this operation? Use updateOrCreate() instead. It finds the first match and updates it with new values, or creates it if not found.