Php Laravel 5表单请求数据预处理
我正在处理一个表单,用户可以更新他们的出生日期。该表单为用户提供了3个单独的字段,分别是Php Laravel 5表单请求数据预处理,php,validation,laravel,laravel-5,Php,Validation,Laravel,Laravel 5,我正在处理一个表单,用户可以更新他们的出生日期。该表单为用户提供了3个单独的字段,分别是天、月和年。当然,在服务器端,我希望将这3个单独的字段视为一个值,即yyyy-mm-dd 因此,在验证和更新数据库之前,我想更改表单请求,通过将年、月和日与-字符串联,创建一个出生日期字段,以创建我需要的日期格式(并可能取消设置原始3个字段) 用我的控制器手动实现这一点不是问题。我可以简单地获取输入,将由-字符分隔的字段连接在一起,然后取消设置它们。然后,我可以在传递命令处理处理处理之前手动验证 然而,我更愿
天
、月
和年
。当然,在服务器端,我希望将这3个单独的字段视为一个值,即yyyy-mm-dd
因此,在验证和更新数据库之前,我想更改表单请求,通过将年
、月
和日
与-
字符串联,创建一个出生日期
字段,以创建我需要的日期格式(并可能取消设置原始3个字段)
用我的控制器手动实现这一点不是问题。我可以简单地获取输入,将由-
字符分隔的字段连接在一起,然后取消设置它们。然后,我可以在传递命令处理处理处理之前手动验证
然而,我更愿意使用FormRequest
来处理验证,并将其注入到我的控制器方法中。因此,我需要一种在执行验证之前实际修改表单请求的方法
我确实发现了以下类似的问题:
它建议覆盖表单请求上的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;
}
您仍然覆盖all()
方法,但请像这样尝试
public function all()
{
$input = $this->all();
$input['date_of_birth'] = $input['year'].'-'.$input['month'].'-'.$input['day'];
$this->replace($input);
return $this->all();
}
那么你自己就不会真正调用这个方法了——在执行规则时,它将由验证器自己调用。注意:这个问题和答案都是在Laravel 5.1发布之前发布的,都是目标5.0。对于5.1及以上版本,请参见@Julia Shestakova或@BenSampo提供的更现代的解决方案
在对自己进行了一些胡闹之后,我想到了以下几点:
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;
}
}
<?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;
}
}
这似乎适合我的需要。我不确定这样做有什么缺点,所以我欢迎任何评论/批评
上面的轮班交换给出的答案也很好。我也需要一种快速而肮脏的方法来完成这项工作。我想使用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其他需要帮助的人。在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();
}
我对Julia Logvina采取了类似的方法,但我认为这种方法是在验证之前添加/修改字段的一种稍微优雅的方法(Laravel 5.1)
我认为这是最好的方法:
在Laravel5.4+中,有一个专门的方法来处理类似的内容,所以请使用它:prepareForValidation
由于Laravel5.4,您可以对FormRequest类使用prepareForValidation
方法
谢谢您的回复。难道没有一种“一次性”的清洁方法吗?它感觉非常脏,每次请求数据时都必须对数据进行操作。通过查看代码,似乎每次请求数据时都会调用all()
函数(即从input
,,,,除了
等)。这是一种非常干净的方法,因为它在FormRequest对象内部被整洁地处理。这意味着控制器和应用程序的其他方面不知道发生了什么。每次调用all()。专注于编写好的、干净的、可维护的代码会有更好的结果:)是的,在这种情况下,这绝对是微不足道的。但从理论上讲,如果这里有很多事情要做,那可能是另一回事。我更喜欢尽可能地编写最佳代码。我会把这种方法比作获得我们在每次迭代中循环通过的数组的长度。这是可行的,优化可能是微不足道的,但一切都在增加。我试图寻找其他方法来覆盖,并得出结论,在Symfony\Component\HttpFoundation\Request
中找到的initialize
方法可能是一种可行的方法。有什么想法吗?它是从构造函数调用的。问题是,all()
方法已经在每次迭代中执行数组循环了。如果您查看原始的all()
方法,就是这样:returnarray\u replace\u recursive($this->input(),$this->files->all())
。因此,进行此修改不会对性能产生任何影响。你正在尝试优化一个不需要优化的过程…+1这实际上是一个非常好的方法,我喜欢。尽管我会通过$source=$this->getInputSource()缓存sourceInput代码>当然,在5.4中,这无疑是问题的最佳解决方案。但是,对于5.4之前的版本(这个问题是在2015年3月提出的,当时的版本是5.0),下面给出的其他答案更合适,例如@Julia Logvina针对5.1给出的答案,这是一个长期支持(LTS)版本JEP,但是,像我这样的人如果在5.x上查找一般主题,仍然会发现这一点,因此我认为提及5.4+;)的解决方案是有效的。)谢谢@Thomas Venturini!使用5.5确实有帮助+1尽管在我提出这个问题时(2015年3月),Laravel 5.1尚未发布(于2015年6月发布),但我会接受这个答案。有关Laravel 5.0,请参阅其他一些答案。谢谢你,朱莉娅!是否有方法更改FormRequest重定向到的位置,或者只有在出现错误时才重定向回?是否有方法更改FormRequest重定向到的位置,或者只有在出现错误时才重定向回?为什么直到版本6.x才记录此方法-/
<?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();
}
}