I'm processing a form where a user can update their date of birth. The form gives the user 3 separate fields for day
, month
and year
. On the server-side of course I want to treat these 3 separate fields as one value i.e. yyyy-mm-dd
.
So before validation and updating my database, I want to alter the form request to create a date_of_birth
field by concatenating year
, month
and day
with -
characters to create the date format I need (And possibly unset the original 3 fields).
Achieving this manually with my controller is not a problem. I can simply grab the input, join the fields together separated by -
characters and unset them. I can then validate manually before passing off to a command to deal with the processing.
However, I would prefer to use a FormRequest
to deal with the validation and have that injected into my controller method. Therefore I need a way of actually modifying the form request before validation is executed.
I did find the following question which is similar: Laravel 5 Request - altering data
It suggests overriding the all
method on the form request to contain the logic for manipulating the data prior to validation.
<?php namespace App\Http\Requests;
class UpdateSettingsRequest extends Request {
public function authorize()
{
return true;
}
public function rules()
{
return [];
}
public function all()
{
$data = parent::all();
$data['date_of_birth'] = 'test';
return $data;
}
This is all well and good for the validation, but overriding the all
method doesn't actually modify the data on the form request object. So when it comes to executing the command, the form request contains the original unmodified data. Unless I use the now overridden all
method to pull the data out.
I'm looking for a more concrete way to modify the data within my form request that doesn't require the calling of a specific method.
Cheers
in laravel 5.1 you can do that
<?php namespace App\Http\Requests;
class UpdateSettingsRequest extends Request {
public function authorize()
{
return true;
}
public function rules()
{
return [];
}
protected function getValidatorInstance()
{
$data = $this->all();
$data['date_of_birth'] = 'test';
$this->getInputSource()->replace($data);
/*modify data before send to validator*/
return parent::getValidatorInstance();
}
Since Laravel 5.4, you can use the prepareForValidation
method on FormRequest classes.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|max:200',
'body' => 'required',
'tags' => 'required|array|max:10',
'is_published' => 'required|boolean',
'author_name' => 'required',
];
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
$this->merge([
'title' => fix_typos($this->title),
'body' => filter_malicious_content($this->body),
'tags' => convert_comma_separated_values_to_array($this->tags),
'is_published' => (bool) $this->is_published,
]);
}
}
There's a more detailed write-up here: https://sampo.co.uk/blog/manipulating-request-data-before-performing-validation-in-laravel
Note: This question and answer were both posted before Laravel 5.1 was released and both target 5.0. For 5.1 and above, see this answer by @Julia Shestakova or this answer by @BenSampo for a more modern solution.
After some messing around myself I've come up with the following:
app/Http/Requests/Request.php
<?php namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
abstract class Request extends FormRequest {
/**
* Override the initialize method called from the constructor to give subclasses
* an opportunity to modify the input before anything happens.
*
* @param array $query
* @param array $request
* @param array $attributes
* @param array $cookies
* @param array $files
* @param array $server
* @param null $content
*/
public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
{
parent::initialize($query, $request, $attributes, $cookies, $files, $server, $content);
// Grab the input
$data = $this->getInputSource()->all();
// Pass it off to modifyInput function
$data = $this->modifyInput($data);
// Replace modified data back into input.
$this->getInputSource()->replace($data);
}
/**
* Function that can be overridden to manipulate the input data before anything
* happens with it.
*
* @param array $data The original data.
* @return array The new modified data.
*/
public function modifyInput(array $data)
{
return $data;
}
}
Then on extending classes you can just override the modifyInput
method like this:
app/Http/Requests/TestRequest.php
<?php namespace App\Http\Requests;
class TestRequest extends Request {
public function authorize()
{
return true;
}
public function rules()
{
return [];
}
/**
* Modify the input.
*/
public function modifyInput(array $data)
{
$data['date_of_birth'] = 'something';
// Make sure to return it.
return $data;
}
}
This seems to work for my needs. I'm not sure of any drawbacks of doing it this way so I welcome any comments/criticism.
The answer given by The Shift Exchange above will also work just fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With