摘要:下面這段代碼是自帶的表單驗證的語法,不太了解的可以先查看文檔也可以使用替換和我們期望的結果是能校驗字段最小值是,最大值是當我單元測試的時候發現,竟然校驗通過了單元測試代碼文檔分析我們看一下文檔驗證中的字段必須具有最小值。
下面這段代碼是Laravel自帶的表單驗證的語法,不太了解的可以先查看文檔
"group_num" => "min:1|max:21" // 也可以使用between替換min和max
我們期望的結果是能校驗group_num字段最小值是1,最大值是21
but !!!
...
當我單元測試的時候發現,竟然校驗通過了!
// 單元測試代碼 $warehouseId = 1; $prods = [ [ "prod_id" => 1, "group_num" => 111, "location" => 1, ] ]; $warehouseLogic = new WarehouseLogic(); $result = $warehouseLogic->addProds($warehouseId, $prods); $this->assertEquals(ErrSvc::ERR_OK, $result["code"]);文檔分析
我們看一下文檔
min:value驗證中的字段必須具有最小值。字符串、數字、數組或是文件大小的計算方式都用 size 方法進行評估。
文章提到數字使用size方法進行評估,我們看一下size方法的文檔
size:value代碼分析驗證的字段必須具有與給定值匹配的大小。對于字符串來說,value 對應于字符數。對于數字來說,value 對應于給定的整數值。對于數組來說,
size 對應的是數組的 count 值。對文件來說,size 對應的是文件大小(單位 kb )。
文檔一切正常,我們翻一翻代碼試著分析下原因
我們找到驗證類的文件并打開:vendorlaravelframeworksrcIlluminateValidationValidator.php
大約在1180行,我們看到validateMin()方法
validateMin()第一行代碼,是對參數個數進行驗證的,可以pass掉第二行代碼,調用了getSize()方法,并對getSize()返回結果直接進行大小比較,問題很有可能就出現在getSize()方法身上
我們看一下getSize()的代碼
getSize()我們可以看到if里面判斷了如果值是數字類型并且$hasNumeric就直接返回原始值,如果返回原始值的話,validateMin()方法應該會正確校驗,所以if條件應該是不成立的
原因很可能就在$hasNumeric這個變量上
$hasNumeric調用了$this->hasRule($attribute, $this->numericRules)方法,并傳了兩個參數過去$attribute:當前屬性名
$this->numericRules:["Numeric", "Integer"]
然后我們看一下$this->hasRule()方法究竟做了什么?
hasRule方法直接調用了$this->getRule()方法,并且將參數原封不動傳遞過去
我們看一下getRule()方法干了什么?
getRule()我們已知$attribute是當前字段名,比如文章舉例用的字段group_num
$this->rules其實就是字段+校驗規則拼裝的數組,格式如下:
既然第一個if語句的兩個變量都知道了,我們就能判斷出第一個條件是不成立的,我們繼續看接下來的代碼
代碼是對當前需要校驗字段的規則進行遍歷,并且格式化
list($rule, $parameters) = $this->parseRule($rule);假設是上圖中的group_num字段,他有3個校驗規則,分別是:required、min、max
第一次循環$rule就是Required,$parameters為空
第二次循環$rule就是Min,$parameters就是[1]
我們會發現parseRule($rule)后,會對規則進行in_array的判斷,$rules是參數(["Numeric", "Integer"])上文有寫
假設我們此時的字段是group_num:第一個規則是required,條件不成立;
第二個規則是Min,條件依然不成立;
第三個規則是Max,條件還是不成立!
getRule()返回值:條件都不成立,方法走完,沒有任何返回值,返回值為null
hasRule()返回值:回到hasRule()方法,會對getRule()方法值進行is_null(),并進行邏輯非處理(!),所以返回值為false
我們接著回到getSize()方法,此時我們就知道$hasNumeric的值是false
所以下面的if條件都不成立,最后Laravel使用mb_strlen()對我們數字類型的值進行了長度計算!!!
解決問題既然我們知道原因在于Laravel對當前字段所有規則進行了in_array($rule, ["Numeric", "Integer"])
所以解決思路就是,如果我們要對字段進行大小進行范圍校驗,我們需要把規則修改成:
"group_num" => "integer|min:1|max:21"
所以文章開頭的校驗,對于數值類型的字段,是錯誤的!
其實這不是一個BUG,單純的是Laravel的校驗機制,不過Laravel文檔寫的很模糊!
所以大家在開發的時候記得一定要認真測試!
原文在自己的博客:Laravel一次單元測試發現的’BUG’,分析并解決問題 - 木魚博客
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28914.html
摘要:最近在項目中引用了一個新標準上傳附件的插件,使用過程中發現了一個很有意思也很頭疼的問題,第一次點擊時瞬間就可以打開文件選擇框,之后再點擊則需要等待恐怖的以上備注使用的是瀏覽器版本這是核心部分代碼,經過二次封裝的。 最近在項目中引用了一個html5新標準上傳附件的插件,使用過程中發現了一個很有意思也很頭疼的問題,第一次點擊時瞬間就可以打開文件選擇框,之后再點擊則需要等待恐怖的8s以上(備...
摘要:如果我們把非布爾值作為條件呢打開控制臺并運行上述代碼,會打印說明條件為真值。在中,真值指的是在布爾值上下文中轉換后的值為真的值。兩個能夠建立元素間一一對應的集合稱為互相對等集合。 showImg(https://segmentfault.com/img/bVbtSvt?w=720&h=360); 為了保證可讀性,本文采用音譯而非直譯。 Javascript 一直是神奇的語言。 不相信我...
摘要:今天用更改了的命名空間名字,然后又用恢復到了原來的命名空間名。結果直接導致以下錯誤問題解決確定你的引導程序沒問題在項目根目錄執行命令解決方案來自傳送門為什么要執行,參考深入 今天用php artisan app:name 更改了app的命名空間名字,然后又用git恢復到了原來的App命名空間名。 結果直接導致以下錯誤:Fatal error: Uncaught exception Re...
摘要:原文首發于我的個人網站卡頓問題出現背景中主要耗能設置為折線圖軸數據量控件最開始軸為類目軸,最近根據情況想改為時間軸卡頓主要表現在顯示和拖動時。初步分析是為導致,因為切換回后就卡頓問題消失。 原文首發于我的個人網站: https://lonhon.top/ 卡頓問題出現背景: ECharts^4.0.4 + Vue^2.5.9 option中主要耗能設置為:折線圖 + Y軸2 + se...
閱讀 1508·2023-04-26 00:25
閱讀 906·2021-09-27 13:36
閱讀 930·2019-08-30 14:14
閱讀 2172·2019-08-29 17:10
閱讀 1006·2019-08-29 15:09
閱讀 1942·2019-08-28 18:21
閱讀 962·2019-08-26 13:27
閱讀 971·2019-08-26 10:58