Laravel 更新有时使用 'INSERT' SQL
Posted
技术标签:
【中文标题】Laravel 更新有时使用 \'INSERT\' SQL【英文标题】:Laravel update sometimes uses 'INSERT' SQLLaravel 更新有时使用 'INSERT' SQL 【发布时间】:2019-12-16 01:32:06 【问题描述】:我在更新 Laravel 中的记录时遇到了一些奇怪的问题。我使用此代码更新记录:
$student = new Student();
$student->exists = true;
$student->reg_number = $request->post('reg_number');
$student->name = $request->post('name');
$student->level_id = $request->post('level_id');
$student->status = $request->post('status');
$student->save();
代码第一次执行良好。但是,当我再次尝试更新同一条记录时,我得到了错误
SQLSTATE[23000]:违反完整性约束:1062 重复条目 键“PRIMARY”的“F17/2019/2019”(SQL:插入
students
(reg_number
、name
、level_id
、updated_at
、created_at
)值 (F17/2019/2019, 约翰·杜斯, 5, 2019-08-08 10:31:52, 2019-08-08 10:31:52))。
但是,过了一段时间,比如半小时左右,我可以再次更新记录而不会出现错误,但只能更新一次。第二次尝试会恢复错误。
我尝试了this question 中讨论的各种其他技术,但结果是相同的。该错误表明 Laravel 选择使用 INSERT
而不是 UPDATE
SQL 语句,而记录存在并且我已明确指定它应该更新现有记录。
有人知道这里发生了什么吗?
我使用 mysql,我的学生表 PRIMARY KEY 是 VARCHAR 类型的 reg_number。学生控制器如下所示:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
protected $fillable = [
'reg_number',
'name',
'level_id',
'status'
];
protected $primaryKey = 'reg_number';
public $incrementing = false;
【问题讨论】:
请不要使用 new Student();对于现有记录,使用 Student::find() 当您设置exists
时,代码会更新现有记录。请按照我的问题中的链接。此外,记录第一次更新的事实应该提示您错误不是由使用new Student()
引起的。
该链接有超过 3 年前的答案,如果你挖掘源代码,我不会太相信存在的属性,还有像 $wasRecentlyCreated
这样的其他属性。获取现有模型的推荐方法是从数据库中对它们进行水合。
@dparoli exists
属性实际上在 Laravel 5.8 中有效。试试看。
在你的情况下它不起作用,你的问题就是这个。我不明白你为什么不想在数据库中找到模型,我错过了什么吗?
【参考方案1】:
我在未发布的代码的其他部分有错误。我有这个功能
public function addStudent(Request $request)
if($request->post('status') !== null)
$this->updateStudent($request);
return false;
...
这就是我在检查 $request->post('status') 时出现错误的地方,它在更新时有时为空。请投票关闭问题,因为错误不是由我发布的代码部分引起的。
我很头疼,因为 Laravel 有时会在错误报告方面模棱两可。如果它说明了导致错误的行号或函数,我会很容易地对其进行调试,并且最终不会发布不相关的问题。
【讨论】:
好吧,你自己找到了 :),我们一直是橡皮鸭。【参考方案2】:尝试将值从 false 更改为 true
public $incrementing = true;
【讨论】:
我已经发现我做错了什么。但是,$incrementing
是必需的,因为主键是 VARCHAR 数据类型。【参考方案3】:
您必须找到要更新的学生。因为 New 总是会创建模型的新实例,当你保存时,它会创建新记录而不是更新。
$student = Student::find($id);
$student->exists = true;
$student->reg_number = $request->post('reg_number');
$student->name = $request->post('name');
$student->level_id = $request->post('level_id');
$student->status = $request->post('status');
$student->save();
另一种更新记录的方法是:
$data = [
// Column values you want to update
'exists' => 'value'
...
'status' => 'value'
];
Student::where('id', $id)->update($data)
【讨论】:
这些都不起作用。请检查我的问题中的链接。它拥有所有这些解决方案。但是,我发现该错误是由我没有发布的代码的其他部分引起的。我将结束这个问题,因为问题实际上与我发布的代码无关。 PS:我的代码仍然会在不修改的情况下更新记录。这是因为当您将exists
设置为记录时,它会使用更新功能,并且不会创建新记录。
@TroubleZero 您可以使用 updateOrCreate 方法来实现。
实际上,我使用了某种updateOrCreate
。我用来调用代码来更新记录的函数是这样的:public function addStudent(Request $request) if($request->post('status') !== null) $this->updateStudent($request); return false;
... 这就是我检查 $request->post('status')
时出现错误的地方,更新时它有时为空。以上是关于Laravel 更新有时使用 'INSERT' SQL的主要内容,如果未能解决你的问题,请参考以下文章
Laravel DB::insert() 和 DB::table()->insert() 的区别
如何使用 PHP 执行 sed -i '/^MAIL_DRIVER=/s/=.*/=log/' .env 之类的东西来更新 laravel dotenv 文件中的变量值