合并表单请求验证以进行存储和更新

Merge Form Request Validation for store and update

我正在使用请求验证来验证用户的输入。

这是UpdateUser:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Gate;

class UpdateUser extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return Gate::allows('update-user');
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {

        $user_id = Arr::get($this->request->get('user'), 'id');

        return [
            'user.firstname'      => 'required|string|max:255',
            'user.lastname'       => 'required|string|max:255',
            'user.email'          => "required|string|email|max:255|unique:users,email,{$user_id}",
            'user.password'       => 'sometimes|nullable|string|min:4|confirmed',
        ];
    }
}

如您所见,发生了一些 update 特定的事情:

authorize() 方法检查用户是否被允许 update-user 并且在 rules 中我排除了当前用户的行是唯一的:

'user.email'          => "required|string|email|max:255|unique:users,email,{$user_id}",

因为我想合并 UpdateUserStoreUser,确定我是更新还是保存的最有效和可读的方法是什么?

这是我目前的做法:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Gate;

class UpdateUser extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        if($this->isUpdating())
        {
            return Gate::allows('update-user');
        }

        return Gate::allows('create-user');
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        if($this->isUpdating()){
            $user_id = Arr::get($this->request->get('user'), 'id');

            return [
               ...
            ];
        }

        return [];
    }
    
    /**
     * @return bool
     */
    protected function isUpdating(){
        return $this->isMethod('put') || $this->isMethod('patch');
    }
}

我想知道我是否可以扩展 FormRequest class 并默认提供 isUpdating()

您的更新和存储方法不是同一请求类型,您的请求实例上有 PUTPATCH 方法,因此您可以像这样检查请求类型:

switch ($request->method()) {
   case 'PATCH':
        // do anything in 'patch request';
        break;

   case 'PUT':
        // do anything in 'put request';
        break;

   default:
       // invalid request
       break;
}

前段时间我了解了一种使用单独验证器 class 进行验证的新方法,我非常喜欢它。让我告诉你

UserValidator

中创建一个目录Validators和一个class
class UserValidator
{
    public function rules(User $user)
    {
        return [
            'user.firstname' => [
                'required',
                'string',
                'max:255',
            ],

            'user.lastname' => [
                'required',
                'string',
                'max:255',
            ],

            'user.email' => [
                $user->exists ? 'sometimes' : null,
                'required',
                'string',
                'email',
                'max:255',
                Rule::unique('users', 'email')->ignore($user->exists ? $user->id : null)
            ],

            'user.password' => [
                $user->exists ? 'sometimes' : null,
                'required',
                'string',
                'min:8'
            ],
        ];
    }

    public function validate(array $data, User $user)
    {
        return validator($data, $this->rules($user))            
            //->after(function ($validator) use ($data, $user) {
            //    Custom validation here if need be
            //})
            ->validate();
    }
}

然后可以在Controller中进行授权

class UserController
{
    use AuthorizesRequests;

    /**
     * @param Request $request
     */
    public function store(Request $request)
    {
        $this->authorize('create_user', User::class);

        $data = (new UserValidator())->validate(
            $request->all(),
            $user = new User()
        );

        $user->fill($data)->save();
    }

    /**
     * @param Request $request
     * @param \App\user $user
     */
    public function update(Request $request, User $user)
    {
        $this->authorize('update_user', $user);

        $data = (new UserValidator())->validate(
            $request->all(),
            $user
        );

        $user->fill($data)->save();
    }
}

这是由(推特用户名)@themsaid 提出并解释的