Laravel,无法更新软删除值
Laravel, Can't update a soft-deleted value
我的数据库中有这个值:
id - name - created_at - updated_at - deleted_at
------------------------------------------------
1 - John - 2018-11-11 - 2018-11-11 - (NULL)
2 - John - 2018-11-11 - 2018-11-11 - 2018-11-11
如果我用我的数据表 (Yajra) 搜索 "John",我只会看到带有 id=1
的 John,因为我正在使用软删除。我的模型是这样的:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class MyModel extends Model
{
use SoftDeletes;
protected $fillable = ['name'];
protected $dates = ['deleted_at'];
}
当我删除(销毁)注册表时,它会在 deleted_at
处放置一个正确的日期。但是当我想编辑(更新)John
时,Validator 给我错误提示该值已被使用。我的更新方法是这样的:
public function update(Request $request, $id)
{
$rules = array(
'name' => 'unique:my_table'
);
$validator = Validator::make($request->all(), $rules);
if ($validator->passes()) {
MyModel::find($id)->update($request->input());
return redirect()->route('myroute')->withFlashSuccess('Ok!');
} else {
return redirect()->back()->withInput()->withErrors($validator);
}
}
我做错了什么?
问题与SoftDeletes
无关,是验证问题。 unique
验证规则非常特殊,因为在更新的情况下,它需要知道在执行验证时可能忽略哪个条目。在后台,规则正在执行 SQL 查询,如
IF EXISTS (
SELECT id
FROM my_table
WHERE name = 'some value'
)
SELECT 1
ELSE
SELECT 0
(可能不是完全相同的查询,但类似)。
如您所见,查询不会考虑是否执行更新。因为您的实体已经存在,所以它将 return 1
因此验证失败,因为它认为验证中的值不是唯一的。
但实际上有一种方法可以使验证对更新有效。您只需将现有实体(正在验证)的 id
作为第三个参数添加到验证规则中。所以你的规则应该是这样的:
$rules = [
'name' => 'unique:my_table,name,'.$id
];
请注意,unique
验证规则还有第二个参数 - 您要在其中搜索的数据库 table 的列。
编辑:
如果唯一约束仅与 未删除 条目相关,这意味着如果相同值的其他出现被标记为已删除,则可以重复使用唯一值,那么它可能需要向 unique
验证规则添加额外的 where()
子句。为此,需要将第四个参数设置为 identifier
列名称,然后我们可以添加额外的 where
子句作为两个参数对。
$rules = [
'name' => 'unique:my_table,name,'.$id.',id,deleted_at,NULL'
];
这会将 where('deleted_at', 'NULL')
(或 whereNull('deleted_at')
)添加到查询中。
此人写了一篇博客post,看起来可以解决您的问题:
https://wisdmlabs.com/blog/laravel-soft-delete-unique-validations/
我不是 100% 确定您要这样做,因为您以后可能希望使用 restore() 方法恢复软删除的数据。在这一点上,你会发生碰撞。
我的数据库中有这个值:
id - name - created_at - updated_at - deleted_at
------------------------------------------------
1 - John - 2018-11-11 - 2018-11-11 - (NULL)
2 - John - 2018-11-11 - 2018-11-11 - 2018-11-11
如果我用我的数据表 (Yajra) 搜索 "John",我只会看到带有 id=1
的 John,因为我正在使用软删除。我的模型是这样的:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class MyModel extends Model
{
use SoftDeletes;
protected $fillable = ['name'];
protected $dates = ['deleted_at'];
}
当我删除(销毁)注册表时,它会在 deleted_at
处放置一个正确的日期。但是当我想编辑(更新)John
时,Validator 给我错误提示该值已被使用。我的更新方法是这样的:
public function update(Request $request, $id)
{
$rules = array(
'name' => 'unique:my_table'
);
$validator = Validator::make($request->all(), $rules);
if ($validator->passes()) {
MyModel::find($id)->update($request->input());
return redirect()->route('myroute')->withFlashSuccess('Ok!');
} else {
return redirect()->back()->withInput()->withErrors($validator);
}
}
我做错了什么?
问题与SoftDeletes
无关,是验证问题。 unique
验证规则非常特殊,因为在更新的情况下,它需要知道在执行验证时可能忽略哪个条目。在后台,规则正在执行 SQL 查询,如
IF EXISTS (
SELECT id
FROM my_table
WHERE name = 'some value'
)
SELECT 1
ELSE
SELECT 0
(可能不是完全相同的查询,但类似)。
如您所见,查询不会考虑是否执行更新。因为您的实体已经存在,所以它将 return 1
因此验证失败,因为它认为验证中的值不是唯一的。
但实际上有一种方法可以使验证对更新有效。您只需将现有实体(正在验证)的 id
作为第三个参数添加到验证规则中。所以你的规则应该是这样的:
$rules = [
'name' => 'unique:my_table,name,'.$id
];
请注意,unique
验证规则还有第二个参数 - 您要在其中搜索的数据库 table 的列。
编辑:
如果唯一约束仅与 未删除 条目相关,这意味着如果相同值的其他出现被标记为已删除,则可以重复使用唯一值,那么它可能需要向 unique
验证规则添加额外的 where()
子句。为此,需要将第四个参数设置为 identifier
列名称,然后我们可以添加额外的 where
子句作为两个参数对。
$rules = [
'name' => 'unique:my_table,name,'.$id.',id,deleted_at,NULL'
];
这会将 where('deleted_at', 'NULL')
(或 whereNull('deleted_at')
)添加到查询中。
此人写了一篇博客post,看起来可以解决您的问题:
https://wisdmlabs.com/blog/laravel-soft-delete-unique-validations/
我不是 100% 确定您要这样做,因为您以后可能希望使用 restore() 方法恢复软删除的数据。在这一点上,你会发生碰撞。