之因此寫繼篇,實際上是來反省的,上一次發表了《ThinkSNS+ 如何計算字符顯示長度》後,有網友幾經測試後告知str_word_count 有問題。html
根據ThinkSNS+ 的進度安排,最近在研發支付功能,因此只能使用週末的時間作了一個兼容性更好的計算方法。git
需求github
從新說下需求:在我天朝 PM 常常會提一種要求,就是例如一個用戶名最多輸入12個漢字,可是英文能夠輸入24個,混排也要知足這個規則。算法
簡言之:單字節字符佔0.5,多字節字符佔1字節。apache
解決函數
閒下來的時候看了上篇文章中的算法,實際上是沒什麼問題的,只是兼容性不夠好,並且寫那個方法時想得過於複雜學習
也不知道當時腦殼裏面都想啥了測試
咱們看上一篇中計算多字節的方法:spa
$double = str_word_count(preg_replace('([a-zA-Z0-9_])', '', $value));
計算方法是剔除咱們需求中容許的單字節,而後經過 str word count 來獲取多字節的個數,其實這個函數是能夠獲取到的,可是部分系統下是不會成功的。還有一個函數就能夠直接獲取多字節的個數 mb strlen 修改後以下:code
$double = mb_strlen(preg_replace('([a-zA-Z0-9_])', '', $str));
而後咱們就能夠正確完成這個需求了,最終實現的 Laravel 驗證規則以下:
/ 添加長度規則Validator::extend('display_length', function ($attribute, $value, array $parameters) { if (empty($parameters)) { throw new \InvalidArgumentException('Parameters must be passed'); } $min = 0; if (count($parameters) === 1) { list($max) = $parameters; } elseif (count($parameters) >= 2) { list($min, $max) = $parameters; } if (! isset($max) || $max < $min) { throw new \InvalidArgumentException('The parameters passed are incorrect'); } // 計算單字節. preg_match_all('/[a-zA-Z0-9_]/', $value, $single); $single = count($single[0]) / 2; // 多子節長度. $double = mb_strlen(preg_replace('([a-zA-Z0-9_])', '', $value)); $length = $single + $double; return $length >= $min && $length <= $max; });
Laravel 經過上面的規則,能夠在表單驗證規則中直接驗證,還支持傳入最小值和最大值。
上面的代碼都是來自於基於 Laravel 開發的開源程序 ThinkSNS+ 中,ThinkSNS+ 採用 apache-2.0 協議開源,我相信能夠做爲不少 Laravel 學習者的學習程序之一。
項目地址:GitHub: https://github.com/zhiyicx/thinksns-plus(點擊star關注研發動態,感謝你們的支持)