首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  PHP

Laravel 中优雅的验证日期需要大于今天

  •  
  •   DavidNineRoc · 2018-09-19 11:53:15 +08:00 · 3226 次点击
    这是一个创建于 443 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 我们有时会碰到一个场景,比如买车票,需要进行查询车票剩余,这时候需要一个日期范围,开始日期必须大于等于今天,结束日期必须大于等于开始日期。

    Version

    • Laravel 5.5.40
    • PHP 7.1

    开始之前,为方便查看结果,在/Exceptions/Handler.php文件捕获了异常 那么我们开始做一个验证吧:

    • 新建一个request并注入到需要验证控制器的方法
    • 下图圈出的红色部分,需改成return true因为我们身份验证一般不在这里验证
    • 如上图,end_date可以很简单的通过start_date来限制时间范围,那么start_date该怎么验证呢?我本来想的是这样的。
    • 通过增加一个额外的字段curr_date,然后start_date通过这个字段限制范围。测试发现实际并不生效。直接进入了控制器打印的数据
    • 调试了一下,我在Illuminate\Validation\Concerns、ValidatesAttributes::validateAfterOrEqual方法跳到compareDates方法,并尝试打印了$this->getValue($parameters[0])这时候的$paramters[0]curr_date总是null
    • 然后查阅了一下源码,知道了原因,直接说能正确验证的方法,再说详细的过程。
    • 正确的方法是这样的
    • 重写父类的prepareForValidation方法,之后再测试
    • 这时候得到想要的验证了

    • 分析一下过程
    • 能通过依赖注入实例化我们想要的对象,这一切都得感谢LaravelIoC容器
    • 容器每次解析完新对象之后,总是会释放一些绑定的事件
    • 这些事件很多都是通过服务提供者来绑定的,我们直接查看config/app.php里有关表单验证的服务提供者
    • 我们可以看到当实现ValidatesWhenResolved对象的类在解析之后会自动调用validate方法
    • 回到新建的IndexTicketRequest类,没有这个方法,去到父类,发现实现了ValidatesWhenResolved,而validate是在traitValidatesWhenResolvedTrait
    • 这个类找到了答案,在validate方法里分三步主要的
    • $this->prepareForValidation() 在验证之前的准备
    • 新建一个验证实例
    • 开始验证
    • 之所以是需要在验证之前设置curr_date,我们来看看新建验证实例便知道答案
    • 这里有一个地方导致我们的问题出现,就是先调用了$this->validationData()方法拿到request的数据,然后再通过$this->container->call([$this, 'rules'])拿到验证规则,所以我们在rules方法写的自然不生效了,之后的验证便无法继续进行

    原文链接-Laravel 中优雅的验证日期需要大于今天

    第 1 条附言  ·  2018-09-19 14:36:12 +08:00

    经 v友 指点,已经原文链接修改使用after_or_equal:today,因为today这个关键字在PHP的strtotime中是合法的关键字,可能成功转换

    30 回复  |  直到 2018-09-25 14:10:03 +08:00
        1
    update   2018-09-19 13:05:08 +08:00
    看懵了。。
        2
    Rekkles   2018-09-19 13:12:58 +08:00
    不知道你想表达什么东西,但是你都用 Laravel 了,不用 Carbon 去做日期处理吗?
        3
    geelaw   2018-09-19 13:15:13 +08:00   ♥ 1
    虽然我不是 PHP/Laravel 用户,但我看了如此精妙的操作之后,简单地查了一下文档:

    https://laravel.com/docs/5.4/validation#rule-after
    http://php.net/manual/en/function.strtotime.php

    为什么不能用

    'start_date' => 'required|date|after_or_equal:today'

    呢?
        4
    belin520   2018-09-19 13:17:08 +08:00
    尾巴的外链才是重点
    但是正文真的不走心啊
        5
    carlclone   2018-09-19 13:26:18 +08:00
    楼上的几位简直打脸,楼主被暴打
        6
    jowan   2018-09-19 13:45:11 +08:00
    ```
    return [
    'start_time' => 'nullable|date|after_or_equal:today',
    'finish_time' => 'nullable|date|after_or_equal:start_time',
    ];
    ```

    验证的字段必须是给定日期后的值,这个日期将会通过 PHP 函数 strtotime 来验证。
    你也可以指定其它的字段来比较日期。

    很简单明了的操作为何被你搞的这么骚
        7
    pkoukk   2018-09-19 13:51:37 +08:00
    我不是 php 用户,我想问下这优雅么?
        8
    cncqw   2018-09-19 13:52:03 +08:00
    一顿源码分析猛如虎
        9
    nothingtodo   2018-09-19 13:54:20 +08:00
    @pkoukk 不优雅,明明能很简单的写个函数非得弄这么复杂,也可能是我看不懂 laravel 吧
        10
    justfindu   2018-09-19 13:56:30 +08:00
    就不能好好看一下文档么
        11
    DavidNineRoc   2018-09-19 14:32:27 +08:00
    @update 建议不要看后面的操作
    @Rekkles 楼上有正确的用法之后,真正的操作只是需要一个时间字符串做参数,让 Laravel 作比较
    @geelaw perfect
    @belin520 哈哈>_<,该怎么做才走心呢 >
    @carlclone 出来就是为了混的,没有什么打不打脸,就是学习到了
    @jowan 没跳到 getDateTimestamp 这个方法详细看,才看到调用了 strtotime
    @pkoukk 那么,实际你应该怎么做呢
    @cncqw 哈哈
    @justfindu 收到
        12
    zavieryip   2018-09-19 14:43:56 +08:00
    自从学了 laravel,每次听到"优雅"总会自觉的替换成"恶心",大概是我境界不够
        13
    DavidNineRoc   2018-09-19 15:06:39 +08:00
    @nothingtodo 写函数很复杂的,我一般都是直接 if (@empty($_GET))

    @zavieryip 是的,对自己不喜欢的东西恶心的是对。如果对什么都有好感那人还有什么意思
        14
    nothingtodo   2018-09-19 15:13:31 +08:00
    @DavidNineRoc if 也很简单啊,鸟哥都吐槽 laravel 复杂,费劲
        15
    lepig   2018-09-19 15:17:54 +08:00
    没全看完 只是觉得正文确实不走心

    `下图圈出的红色部分,需改成 return true 因为我们身份验证一般不在这里验证 ` 虽然我知道想表达的是什么,但是这文字描述跟图文都不匹配好吧.
        16
    lepig   2018-09-19 15:21:42 +08:00
    @lepig 好吧 请无视我的评论. 原因是中间的几张图片没加载出来.导致文字和图片中描述的不相符.不过 v2 这图片看的真蛋疼,每张都必须在新标签打开才能看的清楚
        17
    xjr1022   2018-09-19 15:23:35 +08:00
    还需要自己写吗,虽然我没用过 laravel,我记得 Yii2 就可以直接配置文件里面配置啊,laravel 那肯定也有的,再者这哪里优雅了
        18
    DavidNineRoc   2018-09-19 15:45:48 +08:00
    @lepig 确实有些蛋疼,有时候贴大图还会丢失。
    @xjr1022 有类似的,并不复杂,我在文章有一个分割线,说想去找找源码为什么在 rules 直接增加参数不生效,并分析原因。最后得出结果。
    ********************************************************
    这个框架有一个表单验证器。正常的操作只需要两步
    第一步在 request 类填写验证规则,比如 required, exists 之类的
    3L 6L 的朋友说了用 today,可以在填写验证规则的时候少写一个多余的操作

    ![]( )

    ![]( )

    就这两步,其他都是没用的东西。能看的就看,不能看的跳过就行。
        19
    DavidNineRoc   2018-09-19 15:50:58 +08:00
    @nothingtodo 这个是真理,的确看到吐槽
        20
    alwayshere   2018-09-19 15:55:52 +08:00
    论如何化简为繁
        21
    way2create   2018-09-19 15:57:37 +08:00
    一直懒得看 laravel 因为太优雅了 我比较粗鲁
        22
    achenme   2018-09-19 16:01:15 +08:00
    已经看不懂 php 了。真的绕
        23
    RorschachZZZ   2018-09-19 18:47:07 +08:00
    优雅不优雅不重要,关键是很好用
        24
    leoleoasd   2018-09-19 18:49:17 +08:00


    没人注意到白色主题 ide 吗
        25
    DavidNineRoc   2018-09-20 09:12:24 +08:00
    @alwayshere 是的,因为你没有仔细看
    @way2create 粗鲁人好呀
    @achenme 可能吧
    @RorschachZZZ 我觉得表单验证确实好用,可能我写得乱了点。很多人没有仔细看,人云亦云
    @leoleoasd 其他颜色的 IDE 警告不显眼,不好区分。白色一眼看出来
        26
    bestkayle   2018-09-20 17:36:08 +08:00
    laravel 就是用来训练看源码技能的。。楼主,请问再 Request 里面获取输入的具体的某个字段啊
        27
    bestkayle   2018-09-20 17:36:43 +08:00
    @bestkayle #25 这输入法。。请问怎么在 Request 里面.....
        28
    bestkayle   2018-09-21 15:31:40 +08:00
    上面那个问题太傻逼了。。当时自己把自己懵住了。
        29
    miaotaizi   2018-09-24 23:32:13 +08:00
    Laravel 就得"优雅"
        30
    DavidNineRoc   2018-09-25 14:10:03 +08:00
    @bestkayle 中秋都不过节的吗 >_<,表单类本身继承的 Request 类
    @miaotaizi 你说得对
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2362 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 30ms · UTC 12:41 · PVG 20:41 · LAX 04:41 · JFK 07:41
    ♥ Do have faith in what you're doing.