Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

MThomas's avatar

[Laravel 5] Modify input before validation

I want to modify the input value of a form before it is passed to the validator using the new Request validation in Laravel 5.

So the question is, where can I modify (for example trim the input or encode the input) before it is passed to the validator?

In L4 I would do this before passing the values to Validator::make(), but that step is Handled by a Request validator in L5.

0 likes
51 replies
xingfucoder's avatar

Because of you are using the FormRequest in your Controller method, you can use the $requets->all(), $request->only('yourInput'), ... to manage it.

Try it:

$request->replace(array('inputname' => 'new value'));

//or

$request->merge(array('inputname' => 'new value'));

Here, in the official repository you can find in the Request class the replace method:

 /**
 * Replace the input for the current request.
 *
 * @param array $input
 * @return void
 */
 public function replace(array $input)
 {
     $this->getInputSource()->replace($input);
  }

 /**
  * Merge new input into the current request's input array.
  *
  * @param array $input
  * @return void
  */
  public function merge(array $input)
 {
     $this->getInputSource()->add($input);
  }

https://github.com/laravel/framework/blob/master/src/Illuminate/Http/Request.php

Hope it helps you.

7 likes
ratiw's avatar

I think you can override formatInput() method in your FormRequest subclass to do just that.

4 likes
Cocoon's avatar
Cocoon
Best Answer
Level 7

Cool, I didn't know about that possibility. Inside of the FormRequest I added this function it and it works.

EDIT: THIS FUNCTION HAS BEEN REMOVED FROM THE LARAVEL 5.0 RELEASE VERSION

public function formatInput()
{
  $input = array_map('trim', $this->all());

  $input['first_name'] = ucwords($input['first_name']);
  $input['last_name'] = ucwords($input['last_name']);

  $this->replace($input);

  return $this->all();
}
11 likes
pmall's avatar

It is a great improvement for the FormRequest :)

fdusautoir's avatar

Thanks @Cocoon ! That's very cool. Just a much pretty way to do that :


public function treatment() { $input = (object) $this->all(); $input->firstname = ucfirst($input->firstname); $input->lastname = ucfirst($input->lastname); return (array) $input; }
jhauraw's avatar

I've been using this on L5.0.1:

<?php 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();
    }
}
// Individual Request Class

/**
 * Sanitize input before validation.
 *
 * @return array
 */
public function sanitize()
{
    $input = $this->all();

    $input['phone'] = phoneToDigits($input['phone']);

    $this->replace($input);

    return $this->all();
}
11 likes
Swaz's avatar

Is there a way to do this globally? I would like to trim all input globally.

1 like
pmall's avatar

@Swaz

Is there a way to do this globally? I would like to trim all input globally.

Use a middleware

Swaz's avatar

@pmall Do you have an example of what the middleware might look like?

pmall's avatar

This is pretty basic :

<?php namespace App\Http\Middleware;

use Closure;

class TrimInput {

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $input = $request->all();

        $request->merge(array_map('trim', $input));

        return $next($request);
    }

}
2 likes
martinbean's avatar

You can just overload the all() method in your form request class:

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

    // Format/sanitize data here

    return $attributes;
}
24 likes
SilverPaladin's avatar

@martinbean has the best solution. Using his sample this is what I used to strip the phone number to just numbers.

        $attributes = parent::all();
        $attributes['cell'] = preg_replace("/\D/", "", $attributes['cell']);
        return $attributes;
    }
3 likes
RushVan's avatar

I have added @Cocoon's formatInput function to my FormRequest but it does not seem to be applying the ucwords. The request is being called from the Controller properly as the rules within are working. Is there something extra that needs to be done to call the formatInput method or will everything in the FormRequest be applied automatically?

RachidLaasri's avatar

@Tenzing I believe the formatInput method is no longer working. But you still can override the all method.

1 like
RushVan's avatar

So like this @RachidLaasri?

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

    $request['firstName'] = ucwords($request['firstName']);
    $request['lastName'] = ucwords($request['lastName']);

return $request;

}

Fringe's avatar

@martinbean Thx, overwriting the all() method of the parent also works with the unique validation (checking for ' foo' with 'foo')!

jcobb's avatar

Here is another Middleware similar to @pmall’s. This one transforms certain values by casting them to specific types: Boolean, Integer, and Float.

<?php

namespace Developer\Http\Middleware;

use Closure;

class TransformInput
{
    /**
     * Fields that will be cast to boolean
     */
    const FIELDS_BOOLEAN = [
        'residential',
        'primary',
    ];

    /**
     * Fields that will be cast to integers
     */
    const FIELDS_INTEGER = [
        'page',
        'per_page',
        'category_id',
    ];

    /**
     * Fields that will be cast to floats
     */
    const FIELDS_FLOAT = [
        'price',
        'balance',
        'amount',
    ];


    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure                 $next
     * @param  string|null              $guard
     *
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        foreach ($request->all() as $key => $val) {
            if (in_array($key, self::FIELDS_BOOLEAN)) {
                if (strtoupper($val) === "FALSE") {
                    $request->merge([$key => (bool)false]);
                } else {
                    $request->merge([$key => (bool)$val]);
                }
            } elseif (in_array($key, self::FIELDS_INTEGER)) {
                $request->merge([$key => (int)$val]);
            } elseif (in_array($key, self::FIELDS_FLOAT)) {
                $request->merge([$key => (float)$val]);
            }
        }

        return $next($request);
    }
}
2 likes
pmall's avatar

I went back to a solution like @martinbean 's one. I dont feel like middleware should be the place to do this kind of thing.

1 like
opheliadesign's avatar

With Laravel 5.2.7 the all() method does not seem to be adding the new fields to validation.

For example:

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

        $input['title'] = ucwords($input['title']);
        $input['slug'] = str_slug($input['title']);

        return $input;
    }

public function rules()
    {
       return ['title' => 'required', 'slug' => 'unique:topics',  'description' => 'required']; // Slug is not visible to this
    }
3 likes
bplace's avatar

Had the problem with standard sanitizing needs, like removing all non numeric characters from a phone number, or filling automatically latitude and longitude if submitted empty.

You can't sanitize in the rules() function, using $this->replace, as the call to rules() is made after a call to $this->all(). From FormRequests (Laravel 5.2.10) :

protected function getValidatorInstance()
    {
        $factory = $this->container->make(ValidationFactory::class);

        if (method_exists($this, 'validator')) {
            return $this->container->call([$this, 'validator'], compact('factory'));
        }

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

So I created my App\Requests\Request class :

    /**
     * Replace the input with sanitized values before calling rules()
     *
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function getValidatorInstance()
    {
        $this->sanitizeInput();

        return parent::getValidatorInstance();
    }

    /**
     * Default sanitize function
     */
    protected function sanitizeInput()
    {

    }

Now my FormRequests extend App\Requests\Request, and I fill the sanitizeInput() function with the needed sanitizing, like :

    /**
     * Sanitize before rules()
     */
    protected function sanitizeInput()
    {
        // Autofill alias (aka slug) if submitted empty
        if(empty($this->input('alias'))) {
            $input = $this->all();
            $input['alias'] = Format::alias($this->input('name'));
            $this->replace($input);
            // You may also do $this->offsetSet('alias', Format::alias($this->input('name')));
        }
    }

3 likes
ricardovigatti's avatar

Middlewares are not the right place to put this kind of things. I think that overloading the all() method is the better way of doing that:

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

    // you can add fields
    $attributes['new_input'] = 'some_value';

    // or you can sanitize fields
    $attributes['raw_input'] = preg_replace("@[./-]@", "", $attributes['raw_input']);

    $this->replace($attributes);
    return parent::all();
}

Credits: http://larabrain.com/tips/sanitizing-form-data-before-validating-in-a-laravel-5-form-request

4 likes
trevorg's avatar

Yes @ricardovigatti is right. I think that's the best way to handle input manipulation prior to validation.

I would, however, extract certain aspects, such as trim, to a middleware, if you want that done on every request.

1 like
Next

Please or to participate in this conversation.