Laravel / 嵌套验证
Laravel / nested validation
我正在为基本的页面生成器系统构建一个组件驱动的 API,但在验证方面遇到了障碍。
首先,我想解释一下用例。
如果我们在 /components/ProfileCard.vue
中有一个组件(例如在 Vue 中)
<script>
export default {
props: {
name: String,
age: Number,
avatar: String
}
}
</script>
我正在后端创建一个组件components.php
配置:
<?php
return [
'profile' => [
'component' => 'ProfileCard',
'rules' => [
'name' => [
'required',
],
'age' => [
'required',
'number',
],
'avatar' => [
'required',
]
],
],
];
每次提交个人资料卡组件时都会检查和验证。
为组件创建自定义验证规则,我可以说 "the ProfileCard component is not valid" 但我无法合并/嵌套验证规则:
Component.php
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\Validator;
class Component implements Rule
{
protected $validator = null;
public function passes($attribute, $value)
{
$components = config('components');
$component = $value['component'];
if (isset($components[$component])) {
return false;
}
$c = $components[$component];
$this->validator = Validator::make($value['data'], $c['rules'], $c['messages'] ?? '');
return $this->validator->passes();
}
public function message()
{
if (is_null($this->validator)) {
return 'The component does not exist';
}
return $this->validator->errors();
}
}
有没有人有过做这样的事情的经验,或者有人能指出我正确的解决方案方向吗?
理想情况下,我正在寻找一种在使用 Laravel 的 FormRequest 验证时适用的解决方案,如下所示:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Unique;
use App\Rules\Component;
class CreateUserRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'email' => [
'required',
'email',
new Unique('users', 'email'),
],
'profile' => [
'required',
new Component(),
]
];
}
}
数据会像这样进来:
{
"email": "test@example.com",
"profile": {
"component": "ProfileCard",
"data": {
"name": "Test",
"age": 49,
"avatar": "https://example.com/avatar.png"
}
}
}
我已经用我自己取得的进展更新了问题,你可以在规则的 messages
方法中 return a MessageBag
,但是,这会产生一个小问题,响应返回如下:
"message": "The given data was invalid.",
"errors": {
"profile": [
{
"name": [
"The name field is required."
],
"age": [
"The age field is required."
],
"avatar": [
"The avatar field is required."
],
},
":message"
]
}
显然这是一个改进,但它仍然不可用,我们没有“:message”并且验证错误嵌套在 "profile" 数组中的一个对象中。
你的方法似乎把一个简单的问题复杂化了。我永远不会在验证规则中进行验证。相反,执行依赖于 component
的规则,并在表单请求中相应地调整它。您可以像这样轻松地执行嵌套规则。
[
'profile.name' => 'string',
]
执行表单请求中的其余逻辑。该策略是根据您已经尝试过的请求输入和您的配置文件制定规则。
public function rules()
{
// i do not know how you determine this key
$componentKey = 'profile';
$rules = [
...,
$componentKey => [
'required',
]
];
$inputComponent= $this->input('profile')['component'];
$components = config('components');
// based on your data this seems wrong, but basically fetch the correct config entry
$component = $components[$inputComponent];
foreach ($component['rules'] as $key => $value) {
$rules[$componentKey . '.' . $key] => $value;
}
return $rules;
}
你的代码中有些部分我无法弄清楚你的数据是什么意思,我不知道你是如何获得组件密钥配置文件的,你的代码基于配置和组件字段似乎是错误的,应该而是使用 where 条件进行循环。我认为这可以让您朝着正确的方向前进,此解决方案将解决您的消息问题并且更加简单。
我正在为基本的页面生成器系统构建一个组件驱动的 API,但在验证方面遇到了障碍。
首先,我想解释一下用例。
如果我们在 /components/ProfileCard.vue
<script>
export default {
props: {
name: String,
age: Number,
avatar: String
}
}
</script>
我正在后端创建一个组件components.php
配置:
<?php
return [
'profile' => [
'component' => 'ProfileCard',
'rules' => [
'name' => [
'required',
],
'age' => [
'required',
'number',
],
'avatar' => [
'required',
]
],
],
];
每次提交个人资料卡组件时都会检查和验证。
为组件创建自定义验证规则,我可以说 "the ProfileCard component is not valid" 但我无法合并/嵌套验证规则:
Component.php
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\Validator;
class Component implements Rule
{
protected $validator = null;
public function passes($attribute, $value)
{
$components = config('components');
$component = $value['component'];
if (isset($components[$component])) {
return false;
}
$c = $components[$component];
$this->validator = Validator::make($value['data'], $c['rules'], $c['messages'] ?? '');
return $this->validator->passes();
}
public function message()
{
if (is_null($this->validator)) {
return 'The component does not exist';
}
return $this->validator->errors();
}
}
有没有人有过做这样的事情的经验,或者有人能指出我正确的解决方案方向吗?
理想情况下,我正在寻找一种在使用 Laravel 的 FormRequest 验证时适用的解决方案,如下所示:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Unique;
use App\Rules\Component;
class CreateUserRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'email' => [
'required',
'email',
new Unique('users', 'email'),
],
'profile' => [
'required',
new Component(),
]
];
}
}
数据会像这样进来:
{
"email": "test@example.com",
"profile": {
"component": "ProfileCard",
"data": {
"name": "Test",
"age": 49,
"avatar": "https://example.com/avatar.png"
}
}
}
我已经用我自己取得的进展更新了问题,你可以在规则的 messages
方法中 return a MessageBag
,但是,这会产生一个小问题,响应返回如下:
"message": "The given data was invalid.",
"errors": {
"profile": [
{
"name": [
"The name field is required."
],
"age": [
"The age field is required."
],
"avatar": [
"The avatar field is required."
],
},
":message"
]
}
显然这是一个改进,但它仍然不可用,我们没有“:message”并且验证错误嵌套在 "profile" 数组中的一个对象中。
你的方法似乎把一个简单的问题复杂化了。我永远不会在验证规则中进行验证。相反,执行依赖于 component
的规则,并在表单请求中相应地调整它。您可以像这样轻松地执行嵌套规则。
[
'profile.name' => 'string',
]
执行表单请求中的其余逻辑。该策略是根据您已经尝试过的请求输入和您的配置文件制定规则。
public function rules()
{
// i do not know how you determine this key
$componentKey = 'profile';
$rules = [
...,
$componentKey => [
'required',
]
];
$inputComponent= $this->input('profile')['component'];
$components = config('components');
// based on your data this seems wrong, but basically fetch the correct config entry
$component = $components[$inputComponent];
foreach ($component['rules'] as $key => $value) {
$rules[$componentKey . '.' . $key] => $value;
}
return $rules;
}
你的代码中有些部分我无法弄清楚你的数据是什么意思,我不知道你是如何获得组件密钥配置文件的,你的代码基于配置和组件字段似乎是错误的,应该而是使用 where 条件进行循环。我认为这可以让您朝着正确的方向前进,此解决方案将解决您的消息问题并且更加简单。