Laravel 检查 updateOrCreate 是否执行更新
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45702409/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel check if updateOrCreate performed update
提问by Sergej Fomin
I have the following code in my controller:
我的控制器中有以下代码:
for($i=0; $i<$number_of_tourists; $i++) {
$tourist = Tourist::updateOrCreate(['doc_number' => $request['doc_number'][$i]],
$tourist_to_update);
}
each time "updateOrCreate" works, it does 1 of 3 things:
每次“updateOrCreate”工作时,它会做以下三件事之一:
1) updates model instanse OR
1) 更新模型实例或
2) creates and saves a new one OR
2) 创建并保存一个新的 OR
3) leaves everything unchanged (if model with such values already exists).
3) 保持一切不变(如果具有此类值的模型已经存在)。
I need to check if 'updateOrCreate' has done exactly 1 (updated)and then execute some code.
我需要检查 'updateOrCreate' 是否正好完成了 1(更新),然后执行一些代码。
How can I do it?
我该怎么做?
Thank you in advance!
先感谢您!
回答by Adam
You can figure it out like this:
你可以这样理解:
$tourist = Tourist::updateOrCreate([...]);
if(!$tourist->wasRecentlyCreated && $tourist->wasChanged()){
// updateOrCreate performed an update
}
if(!$tourist->wasRecentlyCreated && !$tourist->wasChanged()){
// updateOrCreate performed nothing, row did not change
}
if($tourist->wasRecentlyCreated){
// updateOrCreate performed create
}
Remarks
评论
In Laravel 5.5 you can finally check if updates have actually taken place with the wasChanged
and isDirty
method.
在 Laravel 5.5 中,您最终可以检查wasChanged
和isDirty
方法是否实际发生了更新。
isDirty()
is true if model attribute has been changed and not saved.wasChanged()
is true if model attribute has been changed and saved.
isDirty()
如果模型属性已更改且未保存,则为 true。wasChanged()
如果模型属性已更改并保存,则为 true。
There is also a property (not method!) wasRecentlyCreated
to check if user was created or not.
还有一个属性(不是方法!)wasRecentlyCreated
来检查用户是否被创建。
$user = factory(\App\User::class)->create();
$user->wasRecentlyCreated; // true
$user->wasChanged(); // false
$user->isDirty(); // false
$user = \App\User::find($user->id);
$user->wasRecentlyCreated; // false
$user->wasChanged(); // false
$user->isDirty(); // false
$user->vorname = 'Max';
$user->wasChanged(); // false
$user->isDirty(); // true
$user->save();
$user->wasChanged(); // true
$user->isDirty(); // false
//You can also check if a specific attribute was changed:
$user->wasChanged('name');
$user->isDirty('name');
回答by patricus
It is pretty easy to determine if the function resulted in an update or an insert (check the wasRecentlyCreated
property). However, when using that function, it is less easy to determine if the update actually happened (if the model exists but is not dirty, no update will be performed). I would suggest not using that function, and splitting out the functionality yourself.
很容易确定函数是导致更新还是插入(检查wasRecentlyCreated
属性)。但是,在使用该函数时,不太容易确定更新是否确实发生(如果模型存在但不脏,则不会执行更新)。我建议不要使用该功能,而是自己拆分功能。
This is the function definition:
这是函数定义:
public function updateOrCreate(array $attributes, array $values = [])
{
$instance = $this->firstOrNew($attributes);
$instance->fill($values)->save();
return $instance;
}
To integrate this into your code, I'd suggest something like:
要将其集成到您的代码中,我建议如下:
for ($i=0; $i<$number_of_tourists; $i++) {
$tourist = Tourist::firstOrNew(['doc_number' => $request['doc_number'][$i]]);
$tourist->fill($tourist_to_update);
// if the record exists and the fill changed data, update will be performed
$updated = $tourist->exists && $tourist->isDirty();
// save the tourist (insert or update)
$tourist->save();
if ($updated) {
// extra code
}
}
回答by Sergej Fomin
@patricus below presented a working way to solve the problem. though @TheFallen here gave a solution which uses Eloquent Events and seems more elegant: Laravel Eloquent Events - implement to save model if Updated
下面的@patricus 提出了解决问题的有效方法。尽管@TheFallen 在这里给出了一个使用Eloquent Events的解决方案,而且看起来更优雅: Laravel Eloquent Events - 实现以在更新时保存模型
回答by Naveed Ali
The model attribute 'wasRecentlyCreated' would only be 'true' if it has just been created.
如果模型属性 'wasRecentlyCreated' 刚刚创建,它只会是 'true'。
There is property named 'changes' in model (it is an array), that determines whether the model has been updated with new values or it has been saved as is without making any changes to its attribute.
模型中有一个名为“changes”的属性(它是一个数组),它确定模型是否已使用新值更新或已按原样保存而不对其属性进行任何更改。
Check the following code snippet:
检查以下代码片段:
// Case 1 : Model Created
if ($model->wasRecentlyCreated) {
} else { // Case 2 : Model Updated
if (count($model->changes)) { // model has been assigned new values to one of its attributes and saved successfully
} else { // model has NOT been assigned new values to one of its attributes and saved as is
}
}
回答by Jera
Okay so I couldn't find a good answer for my scenario.
好的,所以我找不到适合我的场景的好答案。
I was using: $this->created_at == $this->updated_at
however I would sometimes update the record later in the request, which meant that 20% of the time the created_at and updated_at were about 1ms out.
我正在使用:$this->created_at == $this->updated_at
但是我有时会在请求的后面更新记录,这意味着 created_at 和 updated_at 有 20% 的时间大约是 1 毫秒。
To combat this I created something a little more relaxed which allows an extra second between creation and modification.
为了解决这个问题,我创建了一些更轻松的东西,它允许在创建和修改之间多出一秒钟。
public function getRecentlyCreatedAttribute()
{
return $this->wasRecentlyCreated || $this->created_at == $this->updated_at || $this->created_at->diffInSeconds($this->updated_at) <= 1;
}
I can now call $this->recentlyCreated
which will return true if there is a small difference in time (1 second).
我现在可以调用$this->recentlyCreated
which 将返回 true 如果时间差异很小(1 秒)。
Tbh this is the second time I've needed this in a project, I'm posting as I just ended up googling it and coming back to this thread looking for the same answer.
Tbh 这是我第二次在一个项目中需要这个,我发帖是因为我刚刚在谷歌上搜索它并回到这个线程寻找相同的答案。
If someone has a more elegant solution, hmu.
如果有人有更优雅的解决方案,嗯。