hyperf 驗證器的使用

lib-wiki發表於2020-03-22

每個框架的驗證器基本都相同、也有很多用法。以下是個人習慣寫法,歡迎指導。

// 引入元件包
composer require hyperf/validation

// 釋出 Translation 元件的檔案
php bin/hyperf.php vendor:publish hyperf/translation

// 釋出驗證器元件的檔案
php bin/hyperf.php vendor:publish hyperf/validation
<?php

namespace App\Lib\_Validator;

use App\Lib\_Error\ValidateException;
use App\Lib\_Validator\Rules\MobileRule;
use App\Lib\_Validator\Rules\RuleInterface;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Validation\Contract\ValidatorFactoryInterface;

/**
 * 更多內建規則參考:https://learnku.com/docs/laravel/6.x/validation/5144#available-validation-rules
 * accepted  yes、 on 或者是 1。這在驗證是否同意"服務條款"的時候非常有用。
 * active_url URL 一個合法的 URL,根據 PHP 函式 checkdnsrr。
 * date 必須是一個合法的日期,根據 PHP 函式 strtotime
 * date_format:format 必須符合給定的 format 的格式,根據 PHP 函式 date_parse_from_format
 * after:date 在給定日期之後,該日期將被傳遞到 PHP 的 strtotime 函式
 * before:date 在給定日期之前,該日期將被傳遞到 PHP 的 strtotime 函式
 * alpha  全字母
 * alpha_dash 字母、數字、中劃線或下劃線字元
 * alpha_num 全部由字母和數字構成
 * between:min,max 給定的 min 和 max 之間。字串、數字以及檔案都將使用大小規則進行比較
 * confirmed 比如,需要驗證此規則的欄位是  password,那麼在輸入中必須有一個與之相同的 password_confirmation 欄位
 * different:field 必須與指定的 field 欄位的值不同
 * digits:value 必須是一個 數字 並且必須滿足 value 設定的精確長度
 * digits_between:min,max 長度必須介於 min 和 max 之間
 * email 合法的電子郵件地址
 * mobile 合法的手機號碼
 * code 手機簡訊驗證碼
 * exists:table,column,where 必須在指定的資料庫的表中存在 (column、where可選) 例:'email' => 'exists:staff,email,account_id,1'
 * unique:table,column,except,idColumn 資料庫的表中唯一 (except:強制忽略一個給定的 ID)
 * 例: 強制忽略一個給定的 ID : 'email' => 'unique:users,email_address,10'
 *
 * image 必須是一個圖片 (jpeg, png, bmp 或者 gif)
 * in:foo,bar,... 值必須在給定的列表中存在
 * not_in:foo,bar,... 值不在給定的列表中存在
 * integer 整數
 * ip 合法的 IP 地址
 * max:value 值必須小於最大值 value。字串,數值,陣列,檔案大小的計算方式都與 size 規則一致。
 * min:value 值必須大於最小值 value。字串,數值,陣列,檔案大小的計算方式都與 size 規則一致。
 * mimes:foo,bar,... 檔案的 MIME 型別必須在給定的列表中。
 * numeric 數值、數值字串
 * float 浮點數
 * regex:pattern 正規表示式
 * required 必須存在驗證
 * required_if:field,value 如果 field 欄位值等於 value ,那麼該驗證為必須值
 * required_with:foo,bar,... 僅當 其它指定的欄位存在的時候,驗證此規則的值必須存在。
 * required_without:foo,bar,... 僅當 其它指定的欄位 ‘有一個’ 不存在的時候,驗證此規則的值必須存在。
 * required_without_all:foo,bar,... 僅當 其它指定的欄位 ‘都不存在’ 的時候,驗證此規則的值必須存在。
 * same:field 驗證此規則的值必須與給定的 field 欄位的值相同。
 * size:value 對於字串,value 代表字元的個數;對於數字,value 代表它的整數值,對於檔案,value 以KB為單位
 * url 合法的 URL
 * gt:value 大於
 * gte:value 大於等於
 * lt:value 小於
 * lte:value 小於等於
 */
class BaseValidator
{
    protected static $extends = [];

    public static function getValidator(): ValidatorFactoryInterface
    {
        static $validator = null;
        if (is_null($validator)) {
            $container = ApplicationContext::getContainer();
            $validator = $container->get(ValidatorFactoryInterface::class);
            self::initExtends();
            self::registerExtends($validator, self::$extends);
        }

        return $validator;
    }

    protected static function initExtends()
    {
        // 更多自定義的擴充套件
        self::$extends = [
            MobileRule::NAME => new MobileRule,
        ];
    }

    protected static function registerExtends(ValidatorFactoryInterface $validator, array $extends)
    {
        foreach ($extends as $key => $extend) {
            if ($extend instanceof RuleInterface) {
                $validator->extend($key, function (...$args) use ($extend) {
                    return call_user_func_array([$extend, RuleInterface::PASSES_NAME], $args);
                });
                $validator->replacer($key, function (...$args) use ($extend) {
                    return call_user_func_array([$extend, RuleInterface::MESSAGE_NAME], $args);
                });
            }
        }
    }

    /**
     * @param array $data
     * @param array $rules
     * @param array $messages
     * @param bool $firstError
     * @return bool
     * @throws ValidateException
     */
    public static function make(array $data, array $rules, array $messages = [], bool $firstError = true): bool
    {

        $validator = self::getValidator();
        if (empty($messages)) {
            $messages = self::messages();
        }
        $valid = $validator->make($data, $rules, $messages);
        if ($valid->fails()) {
            $errors = $valid->errors();
            $error = $firstError ? $errors->first() : $errors;
            throw new ValidateException($error);
        }
        return true;
    }
    // 這個其實用處不大
    public static function messages(): array
    {
        return [];
    }
}
<?php

namespace App\Lib\_Validator\Rules;


use Hyperf\Validation\Validator;

interface RuleInterface
{
    const PASSES_NAME = 'passes';
    const MESSAGE_NAME = 'message';

    /**
     * @param $attribute
     * @param $value
     * @param $parameters
     * @param Validator $validator
     * @return bool
     */
    public function passes($attribute, $value, $parameters, Validator $validator): bool;

    /**
     *
     * @param $message
     * @param $attribute
     * @param $rule
     * @param $parameters
     * @param Validator $validator
     * @return string
     */
    public function message($message, $attribute, $rule, $parameters, Validator $validator): string;
}
<?php

namespace App\Lib\_Validator\Rules;


use Hyperf\Validation\Validator;

class MobileRule implements RuleInterface
{
    const NAME = 'mobile';


    /**
     * @param $attribute
     * @param $value
     * @param $parameters
     * @param Validator $validator
     * @return bool
     */
    public function passes($attribute, $value, $parameters, Validator $validator): bool
    {
        return preg_match('/^1\d{10}$/', $value);
    }

    /**
     *
     * @param $message
     * @param $attribute
     * @param $rule
     * @param $parameters
     * @param Validator $validator
     * @return string
     */
    public function message($message, $attribute, $rule, $parameters, Validator $validator): string
    {
        return $message;
    }
}
<?php

namespace App\Lib\_Validator;

class DemoValidator extends BaseValidator
{
    public static function test(array $data)
    {
        return self::make($data, [
            'id' => 'required|unique:user,id',
        ]);
    }
    public static function test2(array $data)
    {
        return self::make($data, [
            'phone_number' => 'required|mobile',
        ]);
    }
}
DemoValidator::test($request->all());
DemoValidator::test2($request->all());

BaseValidator::make($request->all(), [
     'nickname' => 'required|unique:user,id',
],[
    // 錯誤資訊應該儘量在驗證器的語言檔案裡面定義(以下是演示)
    'nickname.required'=>'暱稱 必須填寫',
    'nickname.unique'=>':attribute 已經被使用',
])
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章