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

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

Version

  • Laravel 5.5.40
  • PHP 7.1

開始之前,為方便檢視結果,在/Exceptions/Handler.php檔案捕獲了異常

那麼我們開始做一個驗證吧:

  • 新建一個request並注入到需要驗證控制器的方法

  • 下圖圈出的紅色部分,需改成return true因為我們身份驗證一般不在這裡驗證

  • 如上圖,end_date可以很簡單的通過start_date來限制時間範圍,那麼start_date該怎麼驗證呢?我本來想的是這樣的。

  • 通過增加一個額外的欄位curr_date,然後start_date通過這個欄位限制範圍。測試發現實際並不生效。直接進入了控制器列印的資料

  • 除錯了一下,我在IlluminateValidationConcerns、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方法寫的自然不生效了,之後的驗證便無法繼續進行

相關文章