目的:
方便自定義驗證,需要從資料庫讀取的資料,或者一些邏輯性較強的驗證等
有道雲地址:
note.youdao.com/ynoteshare1/index....
laravel在官方文件中有幾種驗證方式 但是這些方式無法滿足,一些邏輯性判斷,比如一些特殊驗證,需要查詢表取資料做對比的
控制器驗證
$this->validate($request,[
'name' => 'required|min:2|max:20',
'age' => 'required|integer',
'sex' => 'required|integer',
],[
'required'=>':attribute 為必填項',
'min' => ':attribute 長度不符合要求',
'integer' => ':attribute 必須是一個整形',
],[ 'name' => '姓名',
'age' => '年齡',
'sex' => '性別',
]);
Validator類驗證
$validator = \Validator::make($request->input(),[
'name' => 'required|min:2|max:20',
'age' => 'required|integer',
'sex' => 'required|integer',
],[
'required'=>':attribute 為必填項',
'min' => ':attribute 長度不符合要求',
'integer' => ':attribute 必須是一個整形',
],[
'name' => '姓名',
'age' => '年齡',
'sex' => '性別',
]);
if($validator->fails()){
foreach ($validator->errors()->all() as $message) {
return ['code'=>-1,'msg'=>$message];
}
}
我追蹤原始碼發現 加上自定義方法後,直接提示找不到這個方法,或者就是直接返回了自定義的錯誤
錯誤資訊:
(1/1) BadMethodCallException Method [validateCheckShopPrice] does not exist.
因為我使用的是Validator::make進行驗證的我找到了這個類中重要的方法
位置 vendor\laravel\framework\src\Illuminate\Validation
protected function resolve(array $data, array $rules, array $messages, array $customAttributes)
{
if (is_null($this->resolver)) {
return new Validator($this->translator, $data, $rules, $messages, $customAttributes);
}
return call_user_func($this->resolver, $this->translator, $data, $rules, $messages, $customAttributes);
}
跟蹤程式碼會發現走的是new Validator
在相同目錄下的檔案中 預設會發現他直接初始化了,那麼怎麼辦呢?
public function __construct(Translator $translator, array $data, array $rules, array $messages = [], array $customAttributes = [])
{
$this->initialRules = $rules;
$this->translator = $translator;
$this->customMessages = $messages;
$this->data = $this->parseData($data);
$this->customAttributes = $customAttributes;
$this->setRules($rules);
}
接著往回看,發現在驗證完成之後,記性了fails()方法的呼叫
public function fails()
{
return ! $this->passes();
}
是不是找到根源了 需要資料是否透過規則
public function passes()
{
$this->messages = new MessageBag;
foreach ($this->rules as $attribute => $rules) {
$attribute = str_replace('\.', '->', $attribute);
foreach ($rules as $rule) {
$this->validateAttribute($attribute, $rule);
if ($this->shouldStopValidating($attribute)) {
break;
}
}
}
foreach ($this->after as $after) {
call_user_func($after);
}
return $this->messages->isEmpty();
}
這是真正驗證的地方
需要注意
$this->validateAttribute($attribute, $rule);
這是驗證規則的地方,我進行了改動
protected function validateAttribute($attribute, $rule)
{
$this->currentRule = $rule;
$initialRule = $rule;
list($rule, $parameters) = ValidationRuleParser::parse($rule);
if ($rule == '') {
return;
}
if (($keys = $this->getExplicitKeys($attribute)) &&
$this->dependsOnOtherFields($rule)) {
$parameters = $this->replaceAsterisksInParameters($parameters, $keys);
}
$value = $this->getValue($attribute);
if ($value instanceof UploadedFile && ! $value->isValid() &&
$this->hasRule($attribute, array_merge($this->fileRules, $this->implicitRules))
) {
return $this->addFailure($attribute, 'uploaded', []);
}
$validatable = $this->isValidatable($rule, $attribute, $value);
/**
* 1.自定義方法的字首都是check
* 2.寫法 check名字:類所在位置 checkShopPrice:\App\Models\Admin\Goods
* 3.驗證如果是字串就提示錯誤 我給出的錯誤提示語均為字串
*/
if(substr($initialRule,0,5) == 'check'){
$initial = array_reverse(explode(':', $initialRule));
$model = new $initial[0];
$tipRes = $model->$initial[1]($value, $parameters, $this->data);
if ($validatable && is_string($tipRes)) {
$this->addCustomFailure($attribute, $rule, $tipRes);
}
}else{
$method = "validate{$rule}";
if ($validatable && ! $this->$method($attribute, $value, $parameters, $this)) {
$this->addFailure($attribute, $rule, $parameters);
}
}
}
註釋的地方是我加入自定義的程式碼
報錯錯誤處理我也重新定義了方法,由於原有格式和目前自己寫的有出入
protected function addCustomFailure($attribute, $rule, $message)
{
$this->messages->add($attribute, $message);
$this->failedRules[$attribute][$rule] = $message;
}
以上程式碼已經封裝好了
使用方法 驗證規則
public $rule = [
'shop_price' => ['required', 'checkShopPrice:\App\Models\Admin\Goods'],
];
//錯誤資訊
protected $message = [
'shop_price.required' => '本店售價必填',
'shop_price.regex' => '本店售價格式不對',
'shop_price.checkShopPrice' => '本店售價格式不對',
];
public function checkForm($request){
try{
$model = new Goods();
$validator = Validator::make($request->all(), $model->rule,$model->message);
if($validator->fails()){
foreach ($validator->errors()->all() as $message) {
return ['code'=>-1,'msg'=>$message];
}
}
return ['code'=>1,'msg'=>self::exec_success];
}catch (ValidationException $e){
return ['code'=>-1,'msg'=>$e->getMessage()];
}
}
public static function checkShopPrice($value, $rule, $data){
if ($value < 0.01) {
return '售價不能小於0.01元';
} else {
return true;
}
}
以上是一種情況,就是每一個模型進行自己的驗證,還有一種情況就是使用公共函式去做,這樣的話 就需要把所有的驗證方法做到一個或者多個方法中,就會混亂 不建議這麼做
本作品採用《CC 協議》,轉載必須註明作者和本文連結