gpt4 book ai didi

php - Laravel 验证 : only allow known properties/attributes, 否则验证失败

转载 作者:行者123 更新时间:2023-12-05 04:01:23 25 4
gpt4 key购买 nike

我们正在构建一个需要精确度的 api 端点。我们希望对 POST/PUT 到服务器的参数强制执行严格验证。

如果 api 用户发送了一个不受支持的 key=value 对(例如,我们允许参数 [first_name, last_name] 而用户包含一个不受支持的参数 [country]),我们想要验证失败。

已尝试构建一个名为 allowed_attributes 的自定义验证器(用作 allowed_attributes:attr1,attr2,...),但要使其在 中可用$validationRules 数组,它必须应用于嵌套/子属性列表的父级(...因为否则我们的自定义验证器无法访问正在验证的属性)。

Validator::extend('allowed_attributes', 'App\Validators\AllowedAttributesValidator@validate');

这给其他验证器带来了问题,然后我们不得不预测这个父/子结构和围绕它的代码,包括错误键和错误消息字符串的额外验证后清理。

tl;dr:非常脏,不是干净的实现。

$validationRules = [
'parent' => 'allowed_attributes:first_name,last_name',
'parent.first_name' => 'required|string|max:40',
'parent.last_name' => 'required|string|max:40'
];

$isValid = Validator::make(['parent' => $request], $validationRules);

var_dump("Validation results: " . ($isValid ? "passed" : "failed"));

关于如何在 Laravel 中更干净地完成此操作的任何想法/建议,而不需要使用父/子关系来访问所有 $request 属性的列表(在自定义验证器中)?

最佳答案

我更喜欢发布一个新答案,因为该方法与之前的方法不同,而且更加简洁。所以我宁愿将这两种方法分开,而不是在同一个答案中混合在一起。

更好的问题处理

自从我上次回答以来,在深入研究验证命名空间的源代码后,我发现最简单的方法是扩展验证器类以实现 passes() 函数来检查你的内容需要。

此实现的好处是还可以毫不费力地正确处理单个数组/对象字段的特定错误消息,并且应该与通常的错误消息翻译完全兼容。

创建自定义验证器类

你应该首先在你的应用程序文件夹中创建一个Validator类(我把它放在app/Validation/Validator.php下)并实现passes 像这样的方法:

<?php

namespace App\Validation;

use Illuminate\Support\Arr;
use Illuminate\Validation\Validator as BaseValidator;

class Validator extends BaseValidator
{
/**
* Determine if the data passes the validation rules.
*
* @return bool
*/
public function passes()
{
// Perform the usual rules validation, but at this step ignore the
// return value as we still have to validate the allowance of the fields
// The error messages count will be recalculated later and returned.
parent::passes();

// Compute the difference between the request data as a dot notation
// array and the attributes which have a rule in the current validator instance
$extraAttributes = array_diff_key(
Arr::dot($this->data),
$this->rules
);

// We'll spin through each key that hasn't been stripped in the
// previous filtering. Most likely the fields will be top level
// forbidden values or array/object values, as they get mapped with
// indexes other than asterisks (the key will differ from the rule
// and won't match at earlier stage).
// We have to do a deeper check if a rule with that array/object
// structure has been specified.
foreach ($extraAttributes as $attribute => $value) {
if (empty($this->getExplicitKeys($attribute))) {
$this->addFailure($attribute, 'forbidden_attribute', ['value' => $value]);
}
}

return $this->messages->isEmpty();
}
}

这实际上会扩展默认的 Validator 类以在 passes 方法上添加附加检查。该检查通过转换为点表示法(以支持数组/对象验证)的输入属性和分配了至少一个规则的属性之间的键来计算数组差异。

替换容器中默认的Validator

那么您错过的最后一步是在服务提供商boot方法中绑定(bind)新的Validator类。为此,您只需重写 Illuminate\Validation\Factory 类的解析器,将其作为'validator' 绑定(bind)到 IoC 容器中:

// Do not forget the class import at the top of the file!
use App\Validation\Validator;

// ...

/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->app->make('validator')
->resolver(function ($translator, $data, $rules, $messages, $attributes) {
return new Validator($translator, $data, $rules, $messages, $attributes);
});
}

// ...

在 Controller 中的实际应用

您无需执行任何特定操作即可使用此功能。只需照常调用 validate 方法即可:

$this->validate(request(), [
'first_name' => 'required|string|max:40',
'last_name' => 'required|string|max:40'
]);

自定义错误信息

要自定义错误消息,您只需在 lang 文件中添加一个翻译键,键等于 forbidden_​​attribute(您可以在 上的自定义验证器类中自定义错误键名称>addFailure 方法调用)。

示例: resources/lang/en/validation.php

<?php

return [
// ...

'forbidden_attribute' => 'The :attribute key is not allowed in the request body.',

// ...
];

注意:此实现仅在 Laravel 5.3 中进行了测试。

关于php - Laravel 验证 : only allow known properties/attributes, 否则验证失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55503686/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com