Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify input before validation on Laravel 5.1

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.

like image 312
Paco Orozco Avatar asked Aug 06 '15 08:08

Paco Orozco


People also ask

What does -> Validate do laravel?

It validates the incoming data. By default, base controller class uses a ValidatesRequests trait which provides a convenient method to validate incoming HTTP requests with a variety of powerful validation rules.

What is the method used to configure validation rules in form request laravel?

Laravel Form Request class comes with two default methods auth() and rules() . You can perform any authorization logic in auth() method whether the current user is allowed to request or not. And in rules() method you can write all your validation rule.

What is nullable in laravel validation?

Using the nullable rule, you are telling Laravel that the field under validation may be null but if it is not null, to validate it against the rest of rules in the array for that key.


2 Answers

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);
like image 192
shock_gone_wild Avatar answered Oct 14 '22 11:10

shock_gone_wild


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');
like image 35
Enijar Avatar answered Oct 14 '22 09:10

Enijar