PHP
Atomically Finding or Creating/Updating Records with Eloquent `firstOrCreate` and `updateOrCreate`
Efficiently manage database records in Laravel using `firstOrCreate` to find an existing record or create a new one, and `updateOrCreate` to update or create atomically.
// 1. Using firstOrCreate: Find a user or create a new one if not found.
// It will look for a user named 'John Doe' with email '[email protected]'.
// If found, it returns the existing user. If not, it creates a new one
// with these attributes and additional 'password' attribute.
$user = App\Models\User::firstOrCreate(
['email' => '[email protected]'], // Attributes to find by
['name' => 'John Doe', 'password' => bcrypt('secret')] // Attributes to create with if not found
);
echo "User (firstOrCreate): " . $user->name . " - " . ($user->wasRecentlyCreated ? 'Created' : 'Found') . "
";
// 2. Using updateOrCreate: Find a post or create a new one, and update attributes.
// It will look for a post by 'user_id' and 'title'.
// If found, it updates its 'content' and 'is_published' attributes.
// If not found, it creates a new post with all provided attributes.
$post = App\Models\Post::updateOrCreate(
['user_id' => $user->id, 'title' => 'My First Post'], // Attributes to find by
['content' => 'This is the updated content.', 'is_published' => true] // Attributes to update or create with
);
echo "Post (updateOrCreate): " . $post->title . " - " . ($post->wasRecentlyCreated ? 'Created' : 'Updated') . "
";
// Make sure User and Post models exist and are fillable for these fields.
// E.g., in App\Models\User.php: protected $fillable = ['name', 'email', 'password'];
// E.g., in App\Models\Post.php: protected $fillable = ['user_id', 'title', 'content', 'is_published'];
How it works: `firstOrCreate` and `updateOrCreate` are powerful Eloquent methods for performing atomic find-or-create and find-or-update operations respectively. `firstOrCreate` attempts to find a record matching the first array of attributes; if it doesn't exist, a new record is created with *all* attributes from both arrays. `updateOrCreate` is similar, but if a record is found, its attributes are updated with the values from the second array, otherwise a new record is created with all provided attributes. These methods help prevent race conditions and simplify logic when dealing with unique constraints or upsert-like operations.