我们有时会遇到一种场景,比如买票,需要查询剩余的票。此时,需要一个日期范围。开始日期必须大于或等于今天,结束日期必须大于或等于开始日期。VersionLaravel5.5.40在PHP7.1开始之前,为了方便查看结果,在/Exceptions/Handler.php文件中捕获了异常,所以我们开始验证一下:新建一个request,注入到需要的方法中验证控制器。下图中红色圈出的部分,需要改成返回true,因为这里一般不验证我们的身份验证。如上图,end_date很容易被start_date限制,那么start_date如何验证呢?我也这么想。通过添加一个附加字段curr_date,然后start_date通过该字段限制范围。测试发现实际上并没有作用。我直接把controller打印出来的数据输入进去调试。我跳转到了Illuminate\Validation\Concerns中的compareDates方法,ValidatesAttributes::validateAfterOrEqual方法,此时尝试打印$this->getValue($parameters[0])$paramters[0]isalwaysnullforcurr_date,然后我检查了源代码。知道原因后直接说正确的验证方法,再说详细过程。正确的做法是这样重写父类的prepareForValidation方法,此时再进行测试,得到想要的验证。分析完流程,我们可以通过依赖注入来实例化我们想要的对象,这都要归功于Laravel的IoCcontainercontainer每次解析出一个新的对象后,总会释放一些绑定的事件。其中许多事件都是通过服务提供商绑定的。我们可以直接在config/app.php中查看表单验证相关的服务提供者。当解析实现ValidatesWhenResolved对象的类时,会自动调用validate方法返回到新建的IndexTicketRequest类。没有这个方法,去父类中发现实现了ValidatesWhenResolved,在trait的ValidatesWhenResolvedTrait类中找到了validate。在validate方法中找到答案,分为三步。主要的$this->prepareForValidation()是验证前的准备工作。创建一个新的验证实例以开始验证。之所以需要在验证前设置curr_date,让我们看看新的验证实例就知道答案了。这里有个地方导致我们的问题是先调用$this->validationData()方法获取请求数据,然后通过$this->container->call([$this,'rules']).那么我们在rules方法中写的自然不会生效,后面的验证也就没法继续了
