Different API and name for nearly identical methods in Eloquent and Query Builder #51987
-
Laravel Version10.10 PHP Version8.1 Database Driver & VersionNo response DescriptionQuery Builder has the following: Whereas Eloquent has this: It effectively does almost the same thing but with slightly different names, probably the API itself got slightly out of sync. Query Builder accepts a callback so that we can give a different array of values depending on whether it already exists or not (https://laravel.com/docs/11.x/queries#update-or-insert): DB::table('users')->updateOrInsert(
['user_id' => $user_id],
fn ($exists) => $exists ? [
'name' => $data['name'],
'email' => $data['email'],
] : [
'name' => $data['name'],
'email' => $data['email'],
'marketable' => true,
],
); which isn't possible with Eloquent Steps To ReproduceNot really necessary as it's part of the Laravel API itself, but here's a very simplified example of my situation (doing dual writes to slowly migrate away from an old DB): // class UserController ...
public function storeOrUpdate(Request $request) {
$legacy = DB::connection('legacy');
$_new = DB::connection('new');
$legacy->beginTransaction();
$_new->beginTransaction();
// assuming type User = { id: int, name: string, surname: string }
// and that User::connection => 'new'
// and that class UserObserver implements ShouldHandleEventsAfterCommit {}
User::updateOrCreate(
attributes: ['id' => $request->id],
values: [ // can't conditionally include id or not (in case user exists in old DB but not in new one)
'id' => $request->id,
'name' => $request->name,
'surname' => $request->surname
]
);
$legacy
->table('Users')
->updateOrInsert( // method name is different
attributes: ['id' => $request->id],
values: fn ($exists) => $exists // I can pass a closure that returns different data, unlike above
? [ 'UserName' => "{$request->surname}, {$request->name}" ]
: [
'UserId' => $request->id
'UserName' => "{$request->surname}, {$request->name}"
]
);
// let's ignore error handling in this example and just jam it in there lol
$legacy->commit();
$_new->commit();
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I think you can also do it using eloquent like this: User::query()->updateOrInsert(
attributes: ['id' => $request->id],
values: values: fn ($exists) => $exists // I can pass a closure that returns different data, unlike above
? [ 'UserName' => "{$request->surname}, {$request->name}" ]
: [
'UserId' => $request->id
'UserName' => "{$request->surname}, {$request->name}"
]
); But you need to consider when using |
Beta Was this translation helpful? Give feedback.
I think you can also do it using eloquent like this:
But you need to consider when using
updateOrInsert
directly with the QueryBuilder syntax, it won’t trigger Eloquent events.