php Laravel 5 Form Request 数据预操作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28854585/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel 5 Form Request data pre-manipulation
提问by Jonathon
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
.
我正在处理一个表单,用户可以在其中更新他们的出生日期。该表单为用户提供了 3 个单独的字段,用于day
、month
和year
。在服务器端,我当然想将这 3 个单独的字段视为一个值,即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).
因此,在验证和更新我的数据库之前,我想更改表单请求以date_of_birth
通过连接来创建一个字段year
,month
并day
使用-
字符来创建我需要的日期格式(并且可能取消设置原始 3 个字段)。
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.
但是,我更愿意使用 aFormRequest
来处理验证并将其注入到我的控制器方法中。因此,我需要一种在执行验证之前实际修改表单请求的方法。
I did find the following question which is similar: Laravel 5 Request - altering data
我确实发现了以下类似的问题: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.
它建议覆盖all
表单请求上的方法以包含在验证之前操作数据的逻辑。
<?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.
这对验证来说一切都很好,但是覆盖该all
方法实际上并没有修改表单请求对象上的数据。所以在执行命令时,表单请求包含原始未修改的数据。除非我使用现在覆盖的all
方法来提取数据。
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
干杯
回答by Julia Shestakova
in laravel 5.1 you can do that
在 Laravel 5.1 中你可以这样做
<?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();
}
回答by BenSampo
Since Laravel 5.4, you can use the prepareForValidation
method on FormRequest classes.
从 Laravel 5.4 开始,您可以prepareForValidation
在 FormRequest 类上使用该方法。
<?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
这里有更详细的文章:https: //sampo.co.uk/blog/manipulating-request-data-before-performing-validation-in-laravel
回答by Jonathon
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 answerby @Julia Shestakova or this answerby @BenSampo for a more modern solution.
注意:这个问题和答案都是在 Laravel 5.1 发布之前发布的,并且都针对 5.0。对于5.1及以上,看到这个答案由@Julia Shestakova或者此答案由@BenSampo一个更现代化的解决方案。
After some messing around myself I've come up with the following:
经过一番折腾,我想出了以下几点:
app/Http/Requests/Request.php
应用程序/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:
然后在扩展类时,您可以modifyInput
像这样覆盖方法:
app/Http/Requests/TestRequest.php
应用程序/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.
上面 The Shift Exchange 给出的答案也可以正常工作。
回答by bmagg
I took a similar approach to Julia Logvina but I think this way is a slightly more elegant way to add/modify fields before validation (Laravel 5.1)
我对 Julia Logvina 采取了类似的方法,但我认为这种方法是一种在验证之前添加/修改字段的更优雅的方法(Laravel 5.1)
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class UpdateSettingsRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [];
}
/**
* Extend the default getValidatorInstance method
* so fields can be modified or added before validation
*
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function getValidatorInstance()
{
// Add new data field before it gets sent to the validator
$this->merge(array('date_of_birth' => 'test'));
// OR: Replace ALL data fields before they're sent to the validator
// $this->replace(array('date_of_birth' => 'test'));
// Fire the parent getValidatorInstance method
return parent::getValidatorInstance();
}
}
This will extend the default getValidatorInstance
so we can modify the input values in the request before it gets to the validator (preventing it from using the original unmodified data). Once the data has been modified, it fires off the original getValidatorInstance
then everything continues as normal.
这将扩展默认值,getValidatorInstance
因此我们可以在请求到达验证器之前修改请求中的输入值(防止它使用原始未修改的数据)。一旦数据被修改,它就会触发原始数据,getValidatorInstance
然后一切照常进行。
You can either use $this->replace(array())
or $this->merge(array())
your new fields into your request. I've included an example of how to do both in the snippet above.
您可以在请求中使用$this->replace(array())
或$this->merge(array())
新字段。我在上面的代码片段中包含了一个如何做到这两点的例子。
replace()
will replace all fields with the array you provide.
replace()
将用您提供的数组替换所有字段。
merge()
will add a new field into your request.
merge()
将在您的请求中添加一个新字段。
回答by Thomas Venturini
I think this is the best approach to do so: Laravel 5.1 Modify input before form request validation
我认为这是最好的方法:Laravel 5.1 Modify input before form request validation
In Laravel 5.4+ there is a dedicated method for stuff like this so use it: prepareForValidation
在 Laravel 5.4+ 中,有一个专门的方法来处理这样的事情,所以使用它: prepareForValidation
回答by Laurence
You still override the all()
method - but try it like this
您仍然覆盖该all()
方法 - 但像这样尝试
public function all()
{
$input = $this->all();
$input['date_of_birth'] = $input['year'].'-'.$input['month'].'-'.$input['day'];
$this->replace($input);
return $this->all();
}
Then you dont actually callthe method yourself - it will be called by the validator itself when doing the rules.
然后您实际上并没有自己调用该方法——它会在执行规则时由验证器本身调用。
回答by snstoller
I too needed a quick and dirty way to accomplish this. I wanted to use The Shift Exchanges solution but it didn't work because of the calls to $this
which creates an infinite recursive loop. A quick change to reference the parent method instead will fix the issue:
我也需要一种快速而肮脏的方法来实现这一点。我想使用 Shift Exchanges 解决方案,但它不起作用,因为调用$this
会创建无限递归循环。快速更改以引用父方法将解决此问题:
public function all()
{
$input = parent::all();
$input['date_of_birth'] = $input['year'].'-'.$input['month'].'-'.$input['day'];
$this->replace($input);
return parent::all();
}
HTH others in need.
HTH 其他需要帮助的人。