How7o
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Reading: Laravel updateOrCreate: Insert or Update Records in Eloquent
Share
How7oHow7o
Font ResizerAa
  • OS
Search
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Follow US
© 2024–2026 How7o. All rights reserved.
How7o > Free Laravel, PHP, WordPress & Server Tutorials > Web Development > Laravel updateOrCreate: Insert or Update Records in Eloquent
Web Development

Laravel updateOrCreate: Insert or Update Records in Eloquent

how7o
By how7o
Last updated: April 19, 2026
8 Min Read
Laravel updateOrCreate method shown in an Eloquent code snippet with insert and update branches
SHARE

Checking whether a record exists and then branching to update() or create() is a common Laravel anti-pattern. Eloquent ships with a handful of helpers that collapse that pattern into a single, atomic call. In this guide, I’ll walk through updateOrCreate, firstOrNew, firstOrCreate, upsert, and the query-builder updateOrInsert — and when to reach for each.

Contents
  • TL;DR
  • The Problem With Manual Exists Checks
  • Using updateOrCreate (Single Record)
  • Using firstOrNew When You Need to Manipulate the Model First
  • firstOrCreate vs updateOrCreate
  • Using upsert for Bulk Inserts or Updates
  • Using updateOrInsert at the Query Builder Level
  • Troubleshooting
    • Duplicate Key Errors With updateOrCreate
    • upsert Does Not Update Any Rows
  • Frequently Asked Questions
  • Related Guides

Originally published March 29, 2024, rewritten and updated April 17, 2026.

TL;DR

Use Model::updateOrCreate([$matchAttributes], [$valuesToSet]) when you want a single record inserted or updated in one call. For multiple rows, use Model::upsert([$rows], $uniqueBy, $updateColumns). If you need to work with the model instance (e.g. run logic before saving), use firstOrNew instead.

The Problem With Manual Exists Checks

The pattern a lot of developers start with looks like this:

if (!Setting::where('key', $settingKey)->exists()) {
    // Insert new record into database
} else {
    // Update the existing record
}

This works, but it runs two queries (one to check, one to write) and has a subtle race condition: between the exists() check and the subsequent insert, another request could create the row, causing a duplicate key error. Eloquent’s built-in methods avoid both problems.

Using updateOrCreate (Single Record)

updateOrCreate is the most direct answer. It takes two arrays: the first is the set of attributes to match on, the second is the set of values to save.

Setting::updateOrCreate(
    ['key' => $settingKey],
    ['value' => $settingValue]
);

If a Setting row with key = $settingKey exists, Eloquent updates its value column. If not, it creates a new row with both key and value set. The method returns the model instance either way, so you can chain further operations:

$setting = Setting::updateOrCreate(
    ['key' => $settingKey],
    ['value' => $settingValue]
);

if ($setting->wasRecentlyCreated) {
    // logic specific to the "created" path
}

The wasRecentlyCreated boolean is useful when you need to know which branch was taken — for example, to fire a “welcome” event only on first insert.

Using firstOrNew When You Need to Manipulate the Model First

updateOrCreate saves immediately. If you need to run logic on the model before it hits the database, use firstOrNew:

$setting = Setting::firstOrNew(['key' => $settingKey]);
$setting->value = $settingValue;
$setting->save();

firstOrNew returns either the existing model or a new unsaved instance. The model only gets persisted when you explicitly call save(). This is handy when you need to inspect $setting->exists, mutate multiple attributes conditionally, or run validation before committing.

If you have a lot of attributes to set, use fill() instead of assigning them one by one:

$setting = Setting::firstOrNew(['key' => $settingKey]);
$setting->fill($settingValues)->save();

fill() respects the model’s $fillable array, so only mass-assignable columns will be set.

firstOrCreate vs updateOrCreate

There’s a third method that’s easy to confuse with the first two: firstOrCreate. The difference is what happens when the row already exists.

  • updateOrCreate — if the row exists, update it with the new values. If not, create it.
  • firstOrCreate — if the row exists, return it unchanged. If not, create it.
  • firstOrNew — same as firstOrCreate, but the new record is not saved until you call save().

Pick the one that matches the write semantics you actually want. Using updateOrCreate when you meant firstOrCreate will silently overwrite data.

Decision tree comparing Laravel Eloquent updateOrCreate, firstOrCreate, firstOrNew, and upsert methods

Using upsert for Bulk Inserts or Updates

When you need to write many rows at once, updateOrCreate in a loop is slow — it runs a SELECT and either an INSERT or UPDATE for every row. Eloquent’s upsert method does the whole operation in a single SQL statement using the database’s native INSERT ... ON DUPLICATE KEY UPDATE (MySQL) or ON CONFLICT ... DO UPDATE (PostgreSQL/SQLite).

Setting::upsert(
    [
        ['key' => 'site_title', 'value' => 'how7o'],
        ['key' => 'site_tagline', 'value' => 'how-to guides'],
        ['key' => 'timezone', 'value' => 'UTC'],
    ],
    uniqueBy: ['key'],
    update: ['value']
);

The three arguments are: the array of rows to insert, the column(s) that uniquely identify each row, and the column(s) to update if a duplicate is found. The uniqueBy columns must have a unique or primary index in the database — upsert relies on the database engine, not on Laravel, to detect duplicates.

Using updateOrInsert at the Query Builder Level

If you’re working with the query builder directly (no Eloquent model), the equivalent method is updateOrInsert:

DB::table('settings')->updateOrInsert(
    ['key' => $settingKey],
    ['value' => $settingValue]
);

This skips the model layer entirely — no events fire, no casts apply, no timestamps are touched. It’s the right choice for lightweight, performance-sensitive writes on tables that don’t have an Eloquent model.

Troubleshooting

Duplicate Key Errors With updateOrCreate

If you see “Duplicate entry” SQL errors, the match attributes you passed do not include the column(s) that actually have the unique index. Make sure the first argument to updateOrCreate references a column backed by a unique or primary key — otherwise Eloquent may try to INSERT a new row even when a duplicate exists.

upsert Does Not Update Any Rows

If upsert returns successfully but nothing gets updated, the columns listed in uniqueBy probably don’t have a unique index in the database. The uniqueBy argument tells Laravel which index to reference — the database itself has to enforce the constraint.

Frequently Asked Questions

What’s the difference between updateOrCreate and firstOrCreate?

<code>updateOrCreate</code> updates the row’s values if it already exists. <code>firstOrCreate</code> leaves the existing row unchanged and only creates a new row if none matches. Choose based on whether you want to overwrite existing values.

How do I insert or update many records at once in Laravel?

Use <code>Model::upsert($rows, $uniqueBy, $updateColumns)</code>. It runs the entire batch in a single SQL statement using the database’s native upsert feature. The columns in <code>uniqueBy</code> must have a unique or primary index.

How do I know whether updateOrCreate inserted or updated the row?

Check the <code>wasRecentlyCreated</code> property on the returned model instance. It is <code>true</code> if the row was just inserted and <code>false</code> if an existing row was updated.

Does updateOrCreate fire Eloquent model events?

Yes. Because <code>updateOrCreate</code> goes through the Eloquent model layer, it fires the <code>creating</code>/<code>created</code> events when inserting and the <code>updating</code>/<code>updated</code> events when updating. If you need to bypass events, use the query builder’s <code>updateOrInsert</code> instead.

Does firstOrNew save the record automatically?

No. <code>firstOrNew</code> returns an unsaved model instance if no match is found. You must call <code>save()</code> on it explicitly. This makes it useful when you need to set additional attributes or run validation before persisting.

Related Guides

  • How to Install Laravel
  • How to Install Composer on Ubuntu
  • How to Install PHP on Ubuntu

For the full API surface and return-value semantics, see the official Laravel Eloquent upserts documentation.

TAGGED:EloquentLaravelmysqlphp

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
[mc4wp_form]
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Copy Link Print
Previous Article Step-by-step guide to upgrading the Linux kernel in CentOS 7 using ELRepo How to Upgrade the Linux Kernel in CentOS 7
Next Article Laravel Eloquent exists method checking if a record exists in a database query How to Check if a Record Exists in Laravel
Leave a Comment

Leave a Reply Cancel reply

You must be logged in to post a comment.

FacebookLike
XFollow
PinterestPin
InstagramFollow
Most Popular
Bun runtime — faster JS toolkit replacing npm in Laravel projects
How to Install Bun Runtime on Ubuntu (And Use It in a Laravel Project)
May 24, 2026
Tailscale mesh — peer-to-peer connections between devices, coordination server
How to Install Tailscale on Ubuntu (Zero-Config Mesh VPN for Self-Hosters)
May 24, 2026
Caddy server — automatic HTTPS, 3-line Caddyfile vs 25-line nginx config
How to Install Caddy Server on Ubuntu (Automatic HTTPS, Drop-in nginx Alternative)
May 24, 2026
Cloudflare Tunnel — outbound-only connection from server, no inbound port forward
How to Install Cloudflare Tunnel on Ubuntu (Expose Local Services, No Port Forwarding)
May 24, 2026
WireGuard encrypted tunnel between server and clients with lock icons
How to Set Up WireGuard VPN on Ubuntu (Server, Linux Client, and iOS)
May 24, 2026

You Might Also Like

Laravel foreign key constraint linking posts.user_id to users.id in a schema diagram
Web Development

How to Add Foreign Keys in Laravel Migration

6 Min Read
Upload files via Ajax with jQuery using FormData
Web Development

How to Upload Files via Ajax with jQuery

4 Min Read
PHP string to float conversion with cast, regex cleanup, NumberFormatter
Web Development

How to Convert a String to Float in PHP

7 Min Read
WordPress logged-in menu swap — register_nav_menus + wp_nav_menu with is_user_logged_in ternary
Web Development

How to Display Different Menus to Logged-In Users in WordPress

7 Min Read
How7o

We provide tips, tricks, and advice for improving websites and doing better search.

Tools

  • Age Calculator
  • Word Counter
  • Image Upscaler
  • Password Generator
  • QR Code Generator
  • See all tools→

Pranks

  • Fake Blue Screen Prank
  • Hacker Typer
  • Fake iMessage Generator
  • Windows XP Crash Prank
  • Windows 11 Update Prank
  • See all prank screens →

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service
  • Sitemap
© 2024–2026 How7o. All rights reserved.
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?