Search code examples
validationlaravelrequestrules

laravel : sanitize request data before validation


there is a UpdateUserRequest form request that verify fields value against its rules defined in rules mathod .it has rules() and authorize() methods by default. i want prevent verifying and updating empty fields (such as password) .

using sometimes in rules is not useful as html inputs will be present in POST request even if they are empty.

array:6 [▼
 "_method" => "PATCH"
 "_token" => "Cz79rRez2f6MG0tTU17nVwXD0X1lNGH1hA7OORjm"
 "name" => "john"
 "email" => "[email protected]"
 "password" => ""
 "password_confirmation" => ""

]

so i should remove empty keys of POST request before using sometimes in rules.
the question is : Where is the best place to purge Request array?
is there any laravel build in method to manage such situations?

P.S :Solution:
@Bogdon solution is still valid and works, but there is another simple ,nice ,neat solution adopted from here:
just override all() method inside form request

 class RegistrationRequest extends Request
  {

...

public function all()
{
    $attributes = parent::all();

    if(isset($attributes['password']) && empty($attributes['password'])) 
        {
            unset($attributes['password']);
        }
    $this->replace($attributes);

    return parent::all();

}

...

}

Solution

  • To make this work you'll need to modify the contents of the App\Http\Requests\Request class to allow a way to sanitize the input (class code taken from this Laracasts post):

    namespace App\Http\Requests;
    
    use Illuminate\Foundation\Http\FormRequest;
    
    abstract class Request extends FormRequest
    {
        /**
         * Validate the input.
         *
         * @param  \Illuminate\Validation\Factory  $factory
         * @return \Illuminate\Validation\Validator
         */
        public function validator($factory)
        {
            return $factory->make(
                $this->sanitizeInput(), $this->container->call([$this, 'rules']), $this->messages()
            );
        }
    
        /**
         * Sanitize the input.
         *
         * @return array
         */
        protected function sanitizeInput()
        {
            if (method_exists($this, 'sanitize'))
            {
                return $this->container->call([$this, 'sanitize']);
            }
    
            return $this->all();
        }
    }
    

    After that you just need to write add sanitize method in the UpdateUserRequest class that removes the password field from the input when it's empty:

    public function sanitize()
    {
        if (empty($this->get('password'))) {
            // Get all input
            $input = $this->all();
            // Remove the password field
            unset($input['password']);
            // Replace the input with the modified one
            $this->replace($input);
        }
    
        return $this->all();
    }
    

    Now using the sometimes rule for the password field will work:

    public function rules()
    {
        return [
            // Other rules go here
            'password' => 'sometimes|required|confirmed'
        ];
    }