使用其他字段的规则验证请求,或者从请求中删除该字段?
简单的例子,我有带有规则的 FormRequest 对象:
public function rules() {
return [
'id' => 'required|integer',
'company_name' => 'required|max:255',
];
}
当我收到带有任何其他字段的 post 请求时,我想在控制器中获取错误/异常,或者我只想获取 id 和 company_name 字段,而没有任何其他字段。它存在于 laravel 中的任何功能,或者我必须以我的方式制作它?
要在 Laravel 中的请求中删除密钥,请使用:
$request->request->remove('key')
您使用 laravel 的帖子请求不仅仅是您的表单输入,因此您需要检查请求以查看里面的内容。
要仅获取所需的字段,您可以使用:
$request->only(['fieldname1', 'fieldname2', 'fieldname3']);
或
$request->except(['fieldnameYouDontWant1', 'fieldnameYouDontWant2', 'fieldnameYouDontWant3']);
以排除您不想要的那些。
从 Laravel 5.5 开始,您可以在控制器中执行此操作:
public function store(StoreCompanyRequest $request)
{
Company::create($request->validated());
}
validated(( 函数仅返回已验证的字段,并删除其他所有字段。
从 Laravel 5.5 开始,您可以直接调用validate
方法Request
class YourController extends Controller
{
public function store(Request $request) {
$cleanData = $request->validate([
'id' => 'required|integer',
'company_name' => 'required|max:255',
]);
// Now you may safely pass $cleanData right to your model
// because it ONLY contains fields that in your rules e.g
$yourModel->create($cleanData);
}
}
不幸的是,这里的大多数答案都错过了原始问题的重点。也就是说,您希望在 FormRequest 类中指定需要验证的字段,然后在控制器中执行以下操作:
Something::create($request->validated());
但是,您可能希望验证特定字段,但不将其传递给控制器中的 create
方法。 执行$request->only()
或$request->except()
的问题在于,您必须重复 FormRequest 类中的字段,或者在模型的 $guarded
属性中重复这些字段。
不幸的是,我发现做你想做的唯一方法如下:
Something::create(collect($request->validated())->forget('field_you_dont_want')->toArray());
编辑2020年10月
感谢Laravel论坛上的人们,在Laravel7中,请求类是可宏的。 因此,更好的答案是编辑app/Providers/AppServiceProvider.php
,在boot()
方法中,您可以添加:
// Extend the validated() method
Request::macro('validatedExcept', function($except = []) {
return Arr::except($this->validated(), $except);
});
您需要添加
use Illuminate'Support'Arr;
到app/Providers/AppServiceProvider.php
的顶端。
然后,您可以使用:
$request->validatedExcept(['field_to_ignore', 'another_field_to_ignore']);
编辑 2022 年 2 月
Laravel现在有safe()
方法,可以让你做到这一点:
$request->safe()->except(['field_to_ignore'])
或者正如GWidgery在他的回答中指出的那样,您可以使用exclude
规则:
public function rules() {
return [
'id' => 'required|integer',
'company_name' => 'required|max:255',
'field_to_ignore' => 'required|exclude',
];
}
您可以使用 except 请求方法,它将为您提供除给定字段之外的字段
$request = $request->except('your_field');
如果要从请求中删除多个字段,可以传递字段数组
$request = $request->except(['field_1','field_2',...])
参考:拉拉维尔请求
当您开始进入嵌套数组元素验证时,事情会变得更加棘手,尤其是在涉及通配符的情况下。 将其放入自定义Request
类中,并将其注入控制器方法。 应涵盖所有情况。
public function authorize()
{
//Dot notation makes it possible to parse nested values without recursion
$original = array_dot($this->all());
$filtered = [];
$rules = collect($this->rules());
$keys = $rules->keys();
$rules->each(function ($rules, $key) use ($original, $keys, &$filtered) {
//Allow for array or pipe-delimited rule-sets
if (is_string($rules)) {
$rules = explode('|', $rules);
}
//In case a rule requires an element to be an array, look for nested rules
$nestedRules = $keys->filter(function ($otherKey) use ($key) {
return (strpos($otherKey, "$key.") === 0);
});
//If the input must be an array, default missing nested rules to a wildcard
if (in_array('array', $rules) && $nestedRules->isEmpty()) {
$key .= ".*";
}
foreach ($original as $dotIndex => $element) {
//fnmatch respects wildcard asterisks
if (fnmatch($key, $dotIndex)) {
//array_set respects dot-notation, building out a normal array
array_set($filtered, $dotIndex, $element);
}
}
});
//Replace all input values with the filtered set
$this->replace($filtered);
//If field changes were attempted, but non were permitted, send back a 403
return (empty($original) || !empty($this->all()));
}
我有一个新的解决方案,在你的表单请求类中创建一个新函数:
public function onlyInRules()
{
return $this->only(array_keys($this->rules()));
}
然后在控制器中,调用 $request->onlyInRules()
而不是$request->all()
这是我猜的最好的方法
$this->offsetUnset('field_1');
在表单请求验证中,您可以像这样使用
protected function prepareForValidation()
{
$this->offsetUnset('field_1');
}
我通过在FormRequest类中覆盖方法validate((做到了这一点。
abstract class MyFormRequest extends FormRequest {
public function validate() {
foreach ($this->request->all() as $key => $value) {
if (!array_key_exists($key, $this->rules())) {
throw new ValidationException("Field " . $key . " is not allowed.");
}
}
parent::validate();
}
}
我认为这不是最好的方法,但它是有效的。我应该升级它以立即显示有关所有错误字段的信息:)
Laravel有一个"排除"验证规则:验证:排除
表格请求
public function rules()
{
return [
'second_hand_smoke' => 'required|boolean',
'flu_vaccination' => 'required|boolean',
'provided' => 'required|boolean|exclude',
];
}
控制器
$request->validated();
返回
array:2[
"second_hand_smoke" => 1
"flu_vaccination" => 1
]
您可以通过控制器执行此操作。您只能将两个或某些字段发送到数据库。使用$request->only()
而不是$request->all()
并传递要保存在数据库中的数据数组。 controller
的store()
方法应如下所示:
public function store(Request $request)
{
ModelName::create($request->only(['id','company_name']));
return redirect('RouteName');
}
$request->validated();
将仅返回经过验证的数据。
在控制器方法中:
public function myController(ValidationRequest $request) {
$data = $request->validated();
}
由于没有人从"测试"的角度回答这个问题,您可以做的是重置请求查询。
request()->query = new 'Symfony'Component'HttpFoundation'InputBag();
还有一种方法,仅适用于Laravel 8,具有更多的功能和冗长:
$request->safe()->all()
另外,它可以很容易地用于搜索和替换$request->all()
。