Separate lookup conditions from update attributes when upserting individual Eloquent models.
Instead of writing manual if ($model = Model::find(...)) { $model->update(...); } else { Model::create(...); } logic, Eloquent provides firstOrCreate() and updateOrCreate().
Both methods accept two arrays:
- Lookup Attributes: Columns used in the
WHEREquery to locate an existing record. - Values: Attributes to set or update when creating or modifying the model.
Finding or Creating Records with firstOrCreate()
If a matching record exists, it is returned untouched. If no record exists, it is created using the merged attributes:
use App\Models\User;
// Looks for a user by email. If not found, creates one with the given name and status.
$user = User::firstOrCreate(
['email' => '[email protected]'], // Lookup conditions
['name' => 'Punyapal Shah', 'status' => 'active'] // Additional attributes on create only
);
Upserting Records with updateOrCreate()
If a matching record exists, it is updated with the second array. If not found, a new record is created with all attributes:
use App\Models\Subscription;
$subscription = Subscription::updateOrCreate(
['user_id' => $user->id, 'plan_id' => 'pro_monthly'], // Lookup conditions
['expires_at' => now()->addMonth(), 'is_active' => true] // Attributes to update or create
);
Inspecting Model Creation State
Check whether the returned model was newly created or already existed using wasRecentlyCreated:
if ($subscription->wasRecentlyCreated) {
logger()->info('New subscription created.');
} else {
logger()->info('Existing subscription updated.');
}
Summary
- First argument defines the
WHEREconstraints. - Second argument specifies the values to set or update.
- Use
$model->wasRecentlyCreatedto run event triggers only on newly created records.
Tags:
Laravel Eloquent Database CRUD