繼:我朝特有需求之--英文字符佔 0.5 個,中文字符佔 1 個

之因此寫繼篇,實際上是來反省的,上一次發表了《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關注研發動態,感謝你們的支持)

相關文章
相關標籤/搜索