PHP
Using `firstOrCreate`, `firstOrNew`, `updateOrCreate` for Atomic Operations
Master Laravel Eloquent's `firstOrCreate`, `firstOrNew`, and `updateOrCreate` methods for atomically retrieving, creating, or updating records, preventing race conditions.
<?php
namespace App\Http\Controllers;
use App\Models\Setting;
use Illuminate\Http\Request;
class SettingController extends Controller
{
/**
* Find a setting or create it if it doesn't exist.
*
* @param \Illuminate\Http\Request $request
* @return \App\Models\Setting
*/
public function getOrCreateSetting(Request $request)
{
$setting = Setting::firstOrCreate(
['key' => 'app_theme'], // Attributes to match against
['value' => 'light'] // Attributes to set if creating
);
// $setting is now the existing 'app_theme' setting or a newly created one.
return $setting;
}
/**
* Find a setting or instantiate a new model instance.
* Does not persist the new model to the database automatically.
*
* @param \Illuminate\Http\Request $request
* @return \App\Models\Setting
*/
public function findOrNewSetting(Request $request)
{
$setting = Setting::firstOrNew(
['key' => 'contact_email'], // Attributes to match against
['value' => '[email protected]'] // Attributes to fill if new
);
// You must call $setting->save() to persist it if it's new.
// if (!$setting->exists) {
// $setting->save();
// }
return $setting;
}
/**
* Update a setting if it exists, otherwise create it.
*
* @param \Illuminate\Http\Request $request
* @return \App\Models\Setting
*/
public function updateOrCreateSetting(Request $request)
{
$setting = Setting::updateOrCreate(
['key' => 'welcome_message'], // Attributes to match against
['value' => $request->input('message', 'Hello Guest!')] // Attributes to update or create
);
// $setting is now the updated or newly created 'welcome_message' setting.
return $setting;
}
}
How it works: These Eloquent methods provide convenient ways to perform atomic find-or-create/update operations. `firstOrCreate()` attempts to find a record matching the first array of attributes; if not found, it creates a new record with both arrays of attributes. `firstOrNew()` behaves similarly but only instantiates a new model without persisting it to the database, requiring an explicit `save()`. `updateOrCreate()` finds a record by the first array of attributes and updates it with the second array; if no matching record is found, it creates a new one using both sets of attributes. These methods are crucial for preventing race conditions and simplifying common database interactions.