Laravel 中優雅的驗證日期需要大於今天

seth-shi發表於2018-09-19
  • 我們有時會碰到一個場景,比如買車票,需要進行查詢車票剩餘,這時候需要一個日期範圍,開始日期必須大於等於今天,結束日期必須大於等於開始日期。

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中優雅的驗證日期需要大於今天

本作品採用《CC 協議》,轉載必須註明作者和本文連結
當神不再是我們的信仰,那麼信仰自己吧,努力讓自己變好,不辜負自己的信仰!

相關文章