lumen驗證類 實現控制器場景驗證

sirping發表於2022-08-05

建立 app\Http\Requests\ValidatorTrait.php trait

<?php

namespace App\Http\Validators;

use Illuminate\Support\Facades\Validator;

trait ValidatorTrait
{
    /**
     * 場景名稱
     * @var null
     */
    protected $scene = null;
    /**
     * 只驗證的規則
     * @var array
     */
    protected $onlyRule=[];

    protected static $obj=null;

    /**
     * 自定義錯誤訊息
     * @var array
     */
    protected $massage=[
        "required"    => ":attribute 不能為空",
        "required_if"    => ":attribute 不能為空",
        "required_unless"    => ":attribute 不能為空",
        "required_with"    => ":attribute 不能為空",
        "between"     => [
            'string'=>":attribute 長度必須在 :min 和 :max 之間",
            'numeric'=>":attribute 必須在 :min 和 :max 之間",
        ],
        "email"       => ":attribute 格式錯誤",
        "regex"       => ":attribute 格式錯誤",
        "mobile"      => ":attribute 格式錯誤",
        'date_format' => ':attribute 與給定的格式 :format 不符合',
        'unique'      => ':attribute 已存在',
        'min'         => ':attribute 最小長度為 :min 位',
        'max'         => ':attribute 最大長度為 :max 字元',
        'in'          => ':attribute 不在操作範圍',
        "numeric"     => ":attribute 不為數字",
        "integer"     => ":attribute 不為整數",
        "string"      => ":attribute 不為字串",
        "date"      => ":attribute 格式錯誤",
        "after"      => ":attribute 大於 :date",
        "gt"      => ":attribute 需大於 :value",
        "exists"      => ":attribute 資料有誤",
        "point"      => ":attribute 只能保留小數點後 :num 位",
        "digits"      => ":attribute 長度為 :digits 位",
        "digits_between"      => ":attribute 長度為 :min 和 :max 之間",
    ];


    /**
     * @return mixed
     */
    protected function makeValidator()
    {
        $validationData = app('request');
        $validator = Validator::make(
            $validationData->all(),
            $this->getRules(),
            $this->massage,
            method_exists($this,'attributes') ? $this->attributes() : []
        );
        if ($validator->fails()) {
            return $this->failedValidation($validator);
        }else{
            return $validationData;
        }
    }

    /**
     * 返回錯誤
     * @param $validator
     * @return mixed
     */
    public function failedValidation($validator)
    {
        return $validator->errors()->first();
    }


    /**
     * 驗證方法
     * @param mixed $scene  場景名稱或驗證規則
     */
    public function make($scene='')
    {
        if(!(self::$obj instanceof self)){
            self::$obj = new self();
        }

        if(!empty($scene)){
            if(is_array($scene)){
                self::$obj->onlyRule = $scene;
            }else{
                self::$obj->scene = $scene;
            }
        }
        return self::$obj->makeValidator();
    }


    /**
     * 獲取 rules
     * @return array
     */
    protected function getRules(): array
    {
        return $this->handleScene(method_exists($this,'rules') ? $this->rules() : []);
    }

    /**
     * 場景驗證
     * @param array $rule
     * @return array
     */
    protected function handleScene(array $rule = []): array
    {
        if($this->onlyRule){
            return $this->handleRule($this->onlyRule,$rule);
        }
        $sceneName = $this->scene;
        if($sceneName && method_exists($this,'scene')){
            $scene = $this->scene();
            if(array_key_exists($sceneName,$scene)) {
                return $this->handleRule($scene[$sceneName],$rule);
            }
        }
        return  $rule;
    }

    /**
     * 處理Rule
     * @param array $sceneRule
     * @param array $rule
     * @return array
     */
    private function handleRule(array $sceneRule,array $rule): array
    {
        $rules = [];
        foreach ($sceneRule as $key => $value) {
            if (is_numeric($key) && array_key_exists($value,$rule)) {
                $rules[$value] = $rule[$value];
            } else {
                $rules[$key] = $value;
            }
        }
        return $rules;
    }
}

在驗證類內裡 use ValidatorTrait

例如下面 TestValidator 驗證類

<?php


namespace App\Http\Validators;



class TestValidator
{
    use ValidatorTrait;

    /**
     * 欄位註解
     * @return array
     */
    public function attributes():array
    {
        return [
            'name'=>'姓名',
            'email'=>'郵件',
        ];
    }

    /**
     * 驗證規則
     * @return array
     */
    public function rules():array
    {
        return [
            'name' => 'required|string|unique:users',
            'email' => 'required|email|unique:users',
        ];
    }

    /**
     * 驗證場景
     * @return array
     */
    public function scene():array
    {
        return [
            //add 場景
            'add' => [
                'name' ,       //複用 rules() 下 name 規則
                'email' => 'email|unique:users'  //重置規則
            ],
            //edit場景
            'edit' => ['name'],
        ];
    }

}
use App\Http\Validators\TestValidator;

public function add(Request $request){
    //驗證所以的
    dd(TestValidator::make());
    //驗證 add 場景的欄位
    dd(TestValidator::make('add'));
    //驗證當前欄位或規則
    dd(TestValidator::make(['id'=>['required'],'status']));
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章