Modify input before validation on Laravel 5.1

13,122

Solution 1

This is a tricky one. I only figured out one way to achieve what you want.

The main point is, that it has no effect for the Validator if you change the Request Values in the rules() function.

You could do a workaround by adding a function to your UserCreateRequest:

protected function getValidatorInstance() {
    $this->sanitize();
    return parent::getValidatorInstance();
}

This overrides the parent's getValidatorInstance();

The parent's getValidatorInstance() method includes

    return $factory->make(
        $this->all(), $this->container->call([$this, 'rules']), $this->messages(), $this->attributes());

Which is reached before your code in the rules() function, so the old values (not affected by the changes in rules()) of $this->all() are used.

If you override that function in your own RequestClass you can manipulate the Request values before calling the actual parent's method.

UPDATE (L5.5)

If you are using the Controllers validate function you could do something like that:

    $requestData = $request->all();

    // modify somehow
    $requestData['firstname'] = trim($requestData['firstname']);

    $request->replace($requestData);

    $values = $this->validate($request, $rules);

Solution 2

You can do this by modifying the request and setting the input value.

$request->request->set('key', 'value');

Or, if you prefer the request helper method.

request()->request->set('key', 'value');

Solution 3

These answers no longer work for me in 5.5

you can use

protected function validationData()
{
    $this->request->add([
        'SomeField' => '..some code to modify it goes here'
    ]);
    return $this->request->all();
}

the add method on request overwrites any existing input for that key.

You can see why this works in Illuminate\Foundation\Http\FormRequest, if you follow the trail

/**
 * Get data to be validated from the request.
 *
 * @return array
 */
protected function validationData()
{
    return $this->all();
}

Solution 4

You can use the prepareForValidation method

protected function prepareForValidation() 
{
    $this->merge(['field' => 'field value' ]) ;
} 

Solution 5

If you are using a request MyClassRequest for keeping your validation then simply override all() method of Request class

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

    //you can modify your inputs here before it is validated
    $attribute['firstname'] = trim($attribute['firstname']);
    $attribute['lastname'] = trim($attribute['lastname']);

    return $attributes;
}

Hope this helps.

Share:
13,122
Paco Orozco
Author by

Paco Orozco

Updated on June 06, 2022

Comments

  • Paco Orozco
    Paco Orozco almost 2 years

    I'm trying to modify an user submitted input before validation success. I've followed this easy instructions, but when I test it on Laravel 5.1, It's not working. Am I doing something wrong?

    This is my Request class on SSHAM\Http\Requests\UserCreateRequest.php

    <?php
    
    namespace SSHAM\Http\Requests;
    
    use SSHAM\Http\Requests\Request;
    
    class UserCreateRequest extends Request
    {
    
        // Some stuff not related with this problem
    
        /**
         * Get the validation rules that apply to the request.
         *
         * @return array
         */
        public function rules()
        {
            // Only for debug
            $prova = $this->all();
            echo "<pre>Inside Request - Before sanitize\n[" . $prova['public_key'] . "]</pre>\n";
    
            // Call a function to sanitize user input
            $this->sanitize();
    
            // Only for debug    
            $prova = $this->all();
            echo "<pre>Inside Request - After sanitize\n[" . $prova['public_key'] . "]</pre>\n";
    
            return [
                'username' => 'required|max:255|unique:users',
                'public_key' => 'openssh_key:public',
            ];
        }
    
        /**
         * Sanitizes user input. In special 'public_key' to remove carriage returns
         */
        public function sanitize()
        {
            $input = $this->all();
    
            // Removes carriage returns from 'public_key' input
            $input['public_key'] = str_replace(["\n", "\t", "\r"], '', $input['public_key']);
    
            $this->replace($input);
        }
    
    }
    

    This is my custom validation rule on SSHAM\Providers\OpenSSHKeyValidatorServiceProvider.php

    <?php
    
    namespace SSHAM\Providers;
    
    use Illuminate\Support\ServiceProvider;
    
    class OpenSSHKeyValidatorServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap the application services.
         *
         * @return void
         */
        public function boot()
        {
            // Registering the validator extension with the validator factory
            \Validator::extend('openssh_key', function ($attribute, $value, $parameters) {
    
                // Some stuff not related with this problem    
    
                // Only for debug
                echo "<pre>Inside Validator value\n[" . $value ."]</pre>\n";
                dd();
    
                return true;
            });
    
        }
    
        // Some stuff not related with this problem    
    }
    

    When I call for debugging I obtain this output:

    Inside Request - Before sanitize
    [blah 
    second line 
    third line]
    
    Inside Request - After sanitize
    [blah second line third line]
    
    Inside Validator value
    [blah 
    second line 
    third line]
    

    Seems that sanitize() is working, but when value is treated on validation class it has not been sanitized.

  • The Anh Nguyen
    The Anh Nguyen over 6 years
    you saved my day. Thanks!
  • shock_gone_wild
    shock_gone_wild over 6 years
    With this method you aren't modifying the input values at all. You just modify how the values are presented within the all method. While this works for the validation rules, if you later want to access an input field in your Controller with $request->get('firstname') you will still get the unmodified value. This means, that you get a value which did not pass the validator at all...
  • karmendra
    karmendra over 6 years
    I agree, If I remember correctly this was a piece of code in my product where intent was not to modify the values but do the validation on modified value, I perceived OP to be on these lines. Why my product didn't need the values modified, as there was a checksum/hash in the input, that needs to be recalculated verified after the validation.
  • Spencer O'Reilly
    Spencer O'Reilly over 6 years
    If you use Input::all() or $request->all() in your controller the values remain modified.
  • Roark
    Roark over 5 years
    to help others with modifying existing input: ` $this->request->add([ 'some_input' => str_replace("foo", "bar", $this->request->get('some_input')) ]); `