验证三个唯一字段和软删除
Posted
技术标签:
【中文标题】验证三个唯一字段和软删除【英文标题】:Validation for three unique fields and soft deletes 【发布时间】:2019-08-13 07:15:15 【问题描述】:去年我创建了一个 laravel 站点,其中包含一个 events 表,我需要三个字段来为任何事件(地点、日期和时间)提供唯一性。我无法设置验证请求来执行此操作,因此我直接通过 phpmyadmin 为这三个字段添加了唯一索引,并捕获了插入重复事件时可能发生的异常。
所以基本上我的 store() 方法有一个像这样的try/catch
:
try
$event = new Event;
$event->place = $request->input('place');
$event->date = $request->input('date');
$event->time = $request->input('time');
$event->save();
return view(...);
catch (\Illuminate\Database\QueryException $e)
// Exception if place-date-time is duplicated
if($e->getCode() === '23000')
return view('event.create')
->withErrors("Selected date and time is not available");
好吧,现在我不得不更改应用程序,以便可以软删除事件,我只是将“deleted_at”字段添加到唯一索引中,认为这会很容易......这种方法不再适用了,所以我'一直在这里和那里阅读这个问题,我唯一得到的是我应该通过一个唯一的验证请求来完成它,但老实说,我只是没有得到这个验证规则的语法,其中三个字段不能是相等,而第四个,deleted_at,为空。
我的应用会检查可用的地点、日期和时间,并且不会让用户选择任何不可用的事件,但无论我告诉他们多少次,总会有人使用浏览器后退按钮并保存事件再次:(
任何帮助将不胜感激。谢谢!
【问题讨论】:
【参考方案1】:这不是解决问题的好方法。 你可以做一些事情来解决这个问题
在插入数据库之前获取特定行(如果数据库中存在) 并存储到变量中。
然后检查数据是否已经存入数据库。
如果数据已经存在,则使用消息包创建自定义验证消息,如下所示。$ifExist = $event
->wherePlace(request->input('place'))
->whereDate(request->input('date'))
->whereTime(request->input('time'))
->exist();
if ($ifExist) return 'already exist';
也许对你有帮助。
【讨论】:
谢谢,这就是我最终所做的,但我仍然更喜欢验证唯一规则解决方案,您对这种情况下的语法有任何线索吗? @Alvaro 您还应该在表格中的位置、日期和时间列上创建一个UNIQUE
多列键,否则这段代码可能容易出现竞争条件 ,如果表中没有 UNIQUE
键,这段代码也不是解决它的好方法。【参考方案2】:
@narayanshama91 指出了正确的方向。
您说您想使用unique
规则来验证输入,但问题是上周Laravel Blog 中有一个帖子警告用户可能通过唯一规则SQL Injection
如果输入是由用户提供。
我强烈建议您在这种情况下不使用此规则,因为您依赖于用户的输入。
在您的情况下,正确的方法是 @narayanshama91 答案。
$ifExist = $event
->wherePlace(request->input('place'))
->whereDate(request->input('date'))
->whereTime(request->input('time'))
->exist();
if ($ifExist)
return 'already exist';
【讨论】:
此外,如果在位置、日期和时间列上没有多列唯一键,此代码很容易出现竞争条件.. @RaymondNijland 同意。我不确定他的情况是否会发生竞争条件(取决于应用程序负载),但你是对的 墨菲定律“任何可能出错的事情都会出错”?始终牢记这一点.. “我不确定他的情况是否会发生竞争条件(取决于应用程序负载)” 此外,用户的增加将增加它在场外发生的机会 感谢您指出这一点,@Charlie。我认为验证规则是一个更优雅的解决方案,但这改变了一切。 感谢@RaymondNijland,问题是如果我设置了一个包含地点、日期和时间的唯一键,并且有一个具有给定值的软删除记录,我无法使用相同的值,因为它与已删除的冲突。将 deleted_at 列添加到唯一键不起作用,因为唯一键似乎允许 NULL 值。以上是关于验证三个唯一字段和软删除的主要内容,如果未能解决你的问题,请参考以下文章