模型中的 Laravel 5 验证

Posted

技术标签:

【中文标题】模型中的 Laravel 5 验证【英文标题】:Laravel 5 validation in model 【发布时间】:2016-09-11 09:55:45 【问题描述】:

我有这样的模型

class test extends Model


public   $rules = [
    'title' => 'required',
    'name' => 'required',
];
protected $fillable = ['title','name'];

还有这样的控制器

public function store(Request $request)

    $test=new test; /// create model object
        $validator = Validator::make($request->all(), [
             $test->rules
        ]);
        if ($validator->fails()) 
            return view('test')->withErrors($validator)
        
        test::create($request->all());
 

验证显示这样的错误

0 字段是必需的。

我想展示这个

名称字段是必需的。 标题字段是必需的。

【问题讨论】:

【参考方案1】:

我解决了

public function store(Request $request)

  $test=new test; /// create model object
    $validator = Validator::make($request->all(),$test->rules);
    if ($validator->fails()) 
        return view('test')->withErrors($validator)
    
    test::create($request->all());

【讨论】:

如果我想让这个通用(如 API),以便可以从任何视图调用它怎么办。我如何将它传递给同一个视图(不知道)。 @VeerShrivastav 也许你可以给自己写一个帮助类?【参考方案2】:

你做错了。 rules 数组应该在您的控制器中,或者更好的是在 Form Request 中。

让我告诉你一个更好的方法:

使用php artisan make:request TestRequest 创建一个新的表单请求文件。

例如TestRequest类:

namespace App\Http\Requests;

use App\Http\Requests\Request;

class TestRequest extends Request

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    
        return true;
    

    /**
     * Get the validation messages.
     *
     * @return array
     */
    public function messages()
    
        return [
            'title.required'    => 'A title is required.',
            'name.required'    => 'The name field is required'
        ];
    

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    
        return [
            'title' => 'required',
            'name' => 'required',
        ];
    

将 request 对象注入到您的控制器方法中。

public function store(TestRequest $request)

    // You don't need any validation, this is already done
    test::create($request->all());

【讨论】:

为什么将规则与模型一起存储不好?为什么要创建一个带有验证登录请求的额外对象? 我来自 Ruby on Rails 背景,使用 Laravel 已经有几年了,个人而言,我更喜欢在模型级别进行验证的方法,主要原因有两个:1. 模型可以更改从用户输入以外的许多地方,维护数据的完整性不仅适用于前端用户,还适用于每个人,包括项目中的所有开发人员。 2. 自定义请求和验证器仅适用于您从控制器获得的属性,它们不会验证模型的所有属性,例如,如果有效购买 2 件商品会使库存变为 -1。 我也很想知道为什么 Laravel 会这样做。虽然我认为这个答案总的来说很好,但我认为这种方式“更好” - “更好”是主观的 这里用户想要将规则放入模型而不是控制器或表单请求中。因为大多数情况下,我们按照框架的建议将规则写入模型中。 我知道这是旧的,但今天仍然适用。不得不说,这个答案从根本上是错误的。在模型上存储规则的方法并没有“更糟”,更不用说“错误的方式”了。 OOP 是关于重用的,如果您在各处重新定义规则,那么您的代码就会出现根本性问题。只需一点点代码,您就可以确保在整个应用程序中都遵循您的规则,无论入口点如何(包括修补程序)。提供单一事实来源总是优于整个应用程序中的大量重新定义。【参考方案3】:

您还可以查看模型中的验证并抛出 ValidationException,该异常将在您的控制器中照常处理(使用错误包等)。例如:

abstract class BaseModel extends Model implements ModelInterface 
    protected $validationRules = [];

    /**
     * Validate model against rules
     * @param array $rules optional array of validation rules. If not passed will validate against object's current values
     * @throws ValidationException if validation fails. Used for displaying errors in view
     */
    public function validate($rules=[]) 
        if (empty($rules))
            $rules = $this->toArray();

        $validator = \Validator::make($rules,$this->validationRules);
        if ($validator->fails())
            throw new ValidationException($validator);
    

    /**
     * Attempt to validate input, if successful fill this object
     * @param array $inputArray associative array of values for this object to validate against and fill this object
     * @throws ValidationException if validation fails. Used for displaying errors in view
     */
    public function validateAndFill($inputArray) 
        // must validate input before injecting into model
        $this->validate($inputArray);
        $this->fill($inputArray);
    

然后在我的控制器中:

public function store(Request $request) 
    $person = $this->personService->create($request->input());

    return redirect()->route('people.index', $person)->with('status', $person->first_name.' has been saved');

终于在我的基础服务类中

abstract class BaseResourceService 
    protected $dataService;
    protected $modelClassName;

    /**
     * Create a resource
     * @param array $inputArray of key value pairs of this object to create
     * @returns $object
     */
    public function create($inputArray) 
        try 
            $arr = $inputArray;
            $object = new $this->modelClassName();
            $object->validateAndFill($arr);
            $this->dataService->create($object);
            return $object;
        
        catch (Exception $exception) 
            $this->handleError($exception);
        
    

如果模型通过验证,它会照常继续。如果出现验证错误,它会返回上一页,并在闪存数据/错误包中显示验证错误。

我很可能会将 $person->validate() 方法移到我的服务类中,但是它仍然可以按上述方式工作。

【讨论】:

【参考方案4】:

您可以通过在 Model 中编写来简单地进行验证。

在您的模型文件中

即模型\Test.php

public static $createRules = [
   'name'=>'required|max:111',
   'email'=>'required|email|unique:users',
];

在控制器中

public function store(Request $request)

     $request->validate(ModalName::$createRules);
     $data = new ModelName();

只要这样做。一切都会好起来的。

【讨论】:

以上是关于模型中的 Laravel 5 验证的主要内容,如果未能解决你的问题,请参考以下文章

laravel 5.4 中两种不同的身份验证模型

使用新模型和保护的 Laravel 身份验证失败:未定义索引:模型

API 验证 laravel 5.7

Laravel 5,验证和显示用户角色

减少对外部 API 的身份验证调用(Laravel 5.6)

如何更改 laravel 中的用户模型以使用其他表进行身份验证而不是用户?