Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 拉威尔口若悬河,如何处理唯一的错误?_Php_Laravel_Eloquent - Fatal编程技术网

Php 拉威尔口若悬河,如何处理唯一的错误?

Php 拉威尔口若悬河,如何处理唯一的错误?,php,laravel,eloquent,Php,Laravel,Eloquent,我有一个MySQL约束来确保复合密钥的唯一性。在我的模型Foo中插入新记录时,我得到了预期的错误: $foo = new Foo(['foo' => 42, 'bar => 1]); $foo->save(); 错误: SQLSTATE[23000]:完整性约束冲突:密钥“Unique”的1062重复条目“42” 避免此错误的一种解决方案是在插入之前查询模型: if (!Foo::where('foo', 42)->where('bar', 1)->first()

我有一个MySQL约束来确保复合密钥的唯一性。在我的模型
Foo
中插入新记录时,我得到了预期的错误:

$foo = new Foo(['foo' => 42, 'bar => 1]);
$foo->save();
错误:

SQLSTATE[23000]:完整性约束冲突:密钥“Unique”的1062重复条目“42”

避免此错误的一种解决方案是在插入之前查询模型:

if (!Foo::where('foo', 42)->where('bar', 1)->first()) {
  $foo = new Foo(['foo' => 42, 'bar => 1]);
  $foo->save();
}
另一种方法是在
preg\u match(/UNIQUE/,$e->message)
true
时捕获异常

有没有更好的解决办法

编辑

我注意到,在
illumb\Database\elount\Builder
Laravel中,无论如何都会执行双重查询,这有点令人伤心:

public function findOrNew($id, $columns = ['*'])
{
    if (! is_null($model = $this->find($id, $columns))) {
        return $model;
    }

    return $this->newModelInstance();
}

您可以使用
first或create
方法:

$foo = Foo::firstOrCreate(['foo' => 42, 'bar' => 1]);
这将在创建记录之前检查数据库中是否存在该记录。如果存在,它将返回记录


有关详细信息:

laravel为您提供了firstOrCreate函数,该函数首先检查数据库中是否存在该值,然后还提供了updateOrCreate函数,用于更新某些值,但最重要的是,如果您只想处理唯一记录,则检查验证规则,您将执行FormRequest并向该字段添加唯一规则,之后laravel将向您提供错误消息,因此您将在客户端处理错误

验证需要在控制器级别完成(如laravel Validator),最好执行
计数()
,而不是
第一次()

当实体存在于数据库中时,有不同的解决方案,具体取决于您想要做什么。例如,您可以执行
updateOrCreate()


或者抛出异常

在一般情况下,您应该使用错误代码而不是任何正则表达式来处理数据库错误

在您的特定情况下,如果您的目的是覆盖/更新现有数据,则最好预先查询或使用自动为您执行此操作的Laravel方法

如果您希望预测错误并处理它,您应该执行以下操作:

试试看{
$foo=新foo(['foo'=>42,'bar'=>1]);
$foo->save();
}catch(\Exception$e){//它实际上是一个QueryException,但它也可以工作
如果($e->getCode()==23000){
//处理重复密钥错误
}
}
请参阅以获取错误代码的详尽列表(但理想情况下,您只需要在非常特定的情况下处理几个特定的错误)


最后,重复密钥更新上的SQL
可能也适用于您,但是如果您这样做是为了无声地忽略新值,那么我建议您改为执行错误处理。

为什么不更新迁移文件以删除约束?我如何检查它是否插入了新条目?如果它只是获得了现有条目?@noox you可以使用
$foo->wasnrecentlycreated
来检查它是否被创建。这超出了我的问题范围,但是我如何才能将($baz()->与
first或create
关联起来呢?我不明白你的意思@noox.@noox我想你必须用必要的(模型、迁移)来提出一个新问题让我们正确理解的信息。如果一开始不应该有唯一索引,我还建议修复数据库结构。如果异常与
$e->code==23000
不匹配,我如何重新显示异常?
从catch块抛出$e
是否重新显示它似乎是受保护的属性:
无法访问受保护的属性\Database\QueryException::$code
@novox抱歉。错过了该选项。是要编写
getCode()
而不是
code
。现已修复
$foo = App\Foo::updateOrCreate(['foo' => 42, 'bar' => 1]);