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;
}
}
以上是一种情况,就是每一个模型进行自己的验证,还有一种情况就是使用公共函数去做,这样的话 就需要把所有的验证方法做到一个或者多个方法中,就会混乱 不建议这么做